martes, 22 de enero de 2013

JQuery: multi listas ordenables

A continuación veremos como implementar una lista de selección, donde podemos elegir varios elementos y pasarlos a otra lista. En esta nueva lista, podremos ordenar los elementos.

Vamos a realizar la generación con HAML y los scripts con JQuery, y el relleno de la lista se hará mediante código ruby, como vimos en el post de cómo crear combos de selección.

La parte que creará las listas será la siguiente:

= select_tag :selectfrom, options_for_select(@lista_elementos.map{|x| [x[:nombre], x[:codigo]]}), :multiple => true, :size => 15

.buttons_containers
  .buttons
    %button#btn-add{:type => "button"}
      = '→'.html_safe
    %br
    %button#btn-remove{:type => "button"}
      = '←'.html_safe

= select_tag :selectto, nil, :multiple => true

.buttons_containers
  .buttons
    %button#btn-up{:type => "button"}
      = '↑'.html_safe
    %br
    %button#btn-down{:type => "button"}
      = '↓'.html_safe


Esto creará las listas, que dando los estilos adecuados, no quedarán así:



Ahora tenemos que meter la funcionalidad, para poder pasar los elementos de una lista a la otra con los botones del medio:

  $('#btn-add').click(function(){
    $('#selectfrom option:selected').each( function() {
      $('#selectto').append("");
      $(this).remove();
    });
  });
  $('#btn-remove').click(function(){
    $('#selectto option:selected').each( function() {
      $('#selectfrom').append("");
      $(this).remove();
    });
  });


Así pasaremos de una lista a otra todas las opciones que estén seleccionadas. Para introducir la ordenación de la lista de la derecha:

  $('#btn-up').bind('click', function() {
    $('#selectto option:selected').each( function() {
      var newPos = $('#selectto option').index(this) - 1;
      if (newPos > -1) {
        $('#selectto option').eq(newPos).before("");
        $(this).remove();
      }
    });
  });

  $('#btn-down').bind('click', function() {
    var countOptions = $('#selectto option').size();
    $('#selectto option:selected').each( function() {
      var newPos = $('#selectto option').index(this) + 1;
      if (newPos < countOptions) {
        $('#selectto option').eq(newPos).after("");
        $(this).remove();
      }
    });
  });


Y así podremos subir o bajar elementos:



Si finalmente queremos tratar los elementos seleccionados para realizar alguna acción, como por ejemplo enviar a otra página, lo podemos hacer con un bucle de JQuery:

  $('#btnsumbit').click(function(){
    $('#selectto option').each(function(index, value){
      alert($(this).val());
    })
  });

Este bucle each de JQuery recorre todos los elementos del select final.