2010-05-22 22 views
14

Tengo dos listas ordenadas una al lado de la otra.Uso de jQuery para insertar dinámicamente en la lista alfabéticamente

Cuando saco un nodo de una lista, quiero insertarlo alfabéticamente en la otra lista. El problema es que quiero sacar solo un elemento y colocarlo nuevamente en la otra lista sin actualizar toda la lista.

Lo extraño es que cuando inserto en la lista de la derecha, funciona bien, pero cuando vuelvo a insertar en la lista de la izquierda, la orden nunca sale bien.

También intenté leer todo en una matriz y ordenarla allí por si el método children() no devuelve las cosas en el orden en que se muestran, pero sigo obteniendo los mismos resultados.

Aquí es mi jQuery:

function moveNode(node, to_list, order_by){ 

    rightful_index = 1; 
    $(to_list) 
     .children() 
     .each(function(){ 
      var ordering_field = (order_by == "A") ? "ingredient_display" : "local_counter"; 

      var compA = $(node).attr(ordering_field).toUpperCase(); 
      var compB = $(this).attr(ordering_field).toUpperCase(); 
      var C = ((compA > compB) ? 1 : 0); 
      if(C == 1){ 
       rightful_index++; 
      } 
     }); 

    if(rightful_index > $(to_list).children().length){ 
     $(node).fadeOut("fast", function(){ 
      $(to_list).append($(node)); 
      $(node).fadeIn("fast"); 
     }); 
    }else{ 
     $(node).fadeOut("fast", function(){ 
      $(to_list + " li:nth-child(" + rightful_index + ")").before($(node)); 
      $(node).fadeIn("fast"); 
     }); 
    } 

} 

Esto es lo que se ve mi HTML como:

<ol> 
<li ingredient_display="Enriched Pasta" ingredient_id="101635" local_counter="1"> 
    <span class="rank">1</span> 
    <span class="rounded-corners"> 
      <span class="plus_sign">&nbsp;&nbsp;+&nbsp;&nbsp;</span> 
      <div class="ingredient">Enriched Pasta</div> 
      <span class="minus_sign">&nbsp;&nbsp;-&nbsp;&nbsp;</span> 
    </span> 
</li> 
</ol> 
+0

¿Ha intentado utilizar el depurador para recorrer su código y asegurarse de que su función de devolución de llamada (...) se comporte correctamente? Firebug o las herramientas de desarrollador IE8 funcionan muy bien para esto. Puede poner un punto de interrupción en el cuerpo de su devolución de llamada. – RMorrisey

+1

miré w3c. No puedo encontrar ninguna mención de los atributos 'ingredient_display',' ingredient_id' o 'local_counter'. aparte de eso, este es un html horrible. Espero que esto no entre en producción en algún lado: \ – Jason

+0

He pisado Firebug y por alguna razón no regresan en el orden correcto para una de las listas ordenadas.Tal vez debería ir por getElementById en su lugar. @jason, esto no es para producción. Esos son atributos definidos por el usuario. ¿Cómo recomendarías arreglar esto? – Dex

Respuesta

26

He creado un jsFiddle with working code para resolver este problema. Estoy incluyendo el código aquí también por si acaso jsFiddle va panza arriba en un futuro lejano:

<ol class="ingredientList"> 
    <li class="ingredient">Apples</li> 
    <li class="ingredient">Carrots</li> 
    <li class="ingredient">Clams</li> 
    <li class="ingredient">Oysters</li> 
    <li class="ingredient">Wheat</li> 
</ol> 
<ol class="ingredientList"> 
    <li class="ingredient">Barley</li> 
    <li class="ingredient">Eggs</li> 
    <li class="ingredient">Millet</li> 
    <li class="ingredient">Oranges</li> 
    <li class="ingredient">Olives</li> 
</ol>​ 

y el jQuery:

$(".ingredient").click(function(){ 
    var element = $(this); 
    var added = false; 
    var targetList = $(this).parent().siblings(".ingredientList")[0]; 
    $(this).fadeOut("fast", function() { 
     $(".ingredient", targetList).each(function(){ 
      if ($(this).text() > $(element).text()) { 
       $(element).insertBefore($(this)).fadeIn("fast"); 
       added = true; 
       return false; 
      } 
     }); 
     if(!added) $(element).appendTo($(targetList)).fadeIn("fast"); 
    }); 
});​ 

Me desnudé el código HTML abajo en aras de la brevedad, por lo querrás modificar mi código para que coincida con el tuyo. Además, si va a usar atributos definidos por el usuario (que no son HTML válidos y no son compatibles oficialmente con ningún navegador ... aunque tampoco dañará nada ... probablemente), recomiendo el prefijo "datos- "para cumplir con la especificación HTML5 Custom Data Attribute. Entonces "ingrediente_id" se convertiría en "data-ingredient_id". Si bien esto aún no se admite en ningún navegador actual, ya que HTML5 no se ha finalizado, es más seguro y más sólido que simplemente definir sus propios atributos. Y una vez que finalice HTML5, sus atributos serán totalmente compatibles.

Editar - Como señaló John en los comentarios, esto no funcionará si necesita admitir caracteres UTF-8. En este caso, debe usar String.prototype.localeCompare() (asegúrese de verificar que el navegador lo admita de acuerdo con la documentación). Para que el código sería algo como esto:

$(".ingredient").click(function(){ 
    var element = $(this); 
    var added = false; 
    var targetList = $(this).parent().siblings(".ingredientList")[0]; 
    $(this).fadeOut("fast", function() { 
     $(".ingredient", targetList).each(function(){ 
      if ($(this).text().localeCompare($(element).text()) > 0) { 
       $(element).insertBefore($(this)).fadeIn("fast"); 
       added = true; 
       return false; 
      } 
     }); 
     if(!added) $(element).appendTo($(targetList)).fadeIn("fast"); 
    }); 
}); 

Here is an updated Fiddle implementing localeCompare.

+0

He probado tu método y funciona cuando solo usas .text(). Sin embargo, el mío también funciona cuando usas .text(). Los nuestros se rompen cuando uso .attr(). Dejé de usar los atributos definidos por el usuario y simplemente intenté jugar con el atributo 'id' y todavía tengo el mismo comportamiento extraño. Una depuración me dice que .children() está, de hecho, iterando en el orden correcto. Esto es muy frustrante – Dex

+0

Necesito ordenar otras formas que alfabéticamente. También necesito poder ordenar por ese campo 'local-counter' en mi HTML original. – Dex

+0

Acabo de actualizar el jsFiddle para ordenar por .attr() y parece que funciona. http://jsfiddle.net/VQu3S/9/ –

-3

que tendría la .text() de cada elemento abetos, luego lo puso en una matriz , clasifique la matriz, luego mueva cada elemento donde los índices de la CLASIFICACIÓN coincidan con DESHABILITADO.

y soy demasiado perezoso para escribir el código para eso y probarlo en este momento :) pero solo una idea de mi forma de abordarlo.

Cuestiones relacionadas