2010-05-22 4 views
14

Ho due elenchi ordinati uno accanto all'altro.Uso di jQuery per inserire dinamicamente la lista in ordine alfabetico

Quando togli un nodo da una lista, desidero inserirlo alfabeticamente nell'altra lista. Il problema è che voglio prendere solo un elemento e rimetterlo nell'altro elenco senza aggiornare l'intera lista.

La cosa strana è che quando inserisco nell'elenco a destra, funziona bene, ma quando inserisco nuovamente nell'elenco a sinistra, l'ordine non viene mai eseguito correttamente.

Inoltre ho provato a leggere tutto in un array e smistamento lì solo nel caso in cui il metodo i bambini() non restituisce le cose nell'ordine in cui vengono visualizzati, ma ho ancora ottenere gli stessi risultati.

Ecco il mio 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"); 
     }); 
    } 

} 

Ecco ciò che il mio html appare come:

<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

Si è provato a utilizzare il debugger per scorrere il codice e assicurarsi che ciascuna funzione (...) di richiamata funzioni correttamente? Gli strumenti di sviluppo Firebug o IE8 funzionano perfettamente per questo. È possibile inserire un punto di interruzione nel corpo della richiamata. – RMorrisey

+1

ho controllato w3c. Non riesco a trovare alcuna menzione degli attributi 'ingredient_display',' ingredient_id' o 'local_counter'. a parte questo, questo è un httml orribile. spero che questo non vada in produzione da qualche parte: \ – Jason

+0

Ho passato attraverso l'uso di firebug e per qualche motivo non tornano nell'ordine corretto per una delle liste ordinate.Forse dovrei andare su getElementById invece. @jason, questo non è per la produzione. Quelli sono attributi definiti dall'utente. Come consiglieresti di aggiustarlo? – Dex

risposta

26

Ho creato un jsFiddle with working code per risolvere questo problema. Sono compresi il codice qui pure nel caso in cui jsFiddle va pancia in su in un lontano futuro:

<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>​ 

e 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"); 
    }); 
});​ 

ho messo a nudo il codice HTML giù per brevità, così vorrete modificare il mio codice per abbinare il vostro. Inoltre, se intendi utilizzare attributi definiti dall'utente (che non sono HTML validi e non sono ufficialmente supportati da alcun browser ... anche se non danneggerà nulla ... probabilmente), ti consiglio di anteporre loro "data- "conforme alla specifica HTML5 Custom Data Attribute. Quindi "ingrediente_id" diventerebbe "data-ingredient_id". Anche se questo non è ancora supportato su nessun browser corrente poiché HTML5 non è stato finalizzato, è più sicuro e più robusto rispetto alla semplice definizione dei propri attributi. E una volta finalizzato HTML5, i tuoi attributi saranno pienamente supportati.

Modifica - Come ha sottolineato John nei commenti, questo non funzionerà se è necessario supportare i caratteri UTF-8. In questo caso è necessario utilizzare String.prototype.localeCompare() (assicurarsi di controllare che il browser lo supporti come da documentazione). In modo che il codice sarebbe simile a questa:

$(".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

Ho provato il tuo metodo e funziona quando usi .text(). Tuttavia, il mio funziona anche quando usi .text(). I nostri si rompono entrambi quando uso .attr(). Ho smesso di usare gli attributi definiti dall'utente e ho semplicemente provato a giocare con l'attributo 'id' e ho ancora lo stesso strano comportamento. Un debug mi dice che .children() sta, infatti, iterando nell'ordine corretto. Questo è così frustrante. – Dex

+0

Ho bisogno di ordinare altri modi oltre che alfabeticamente. Devo anche essere in grado di ordinare per quel campo 'local-counter' nel mio codice HTML originale. – Dex

+0

Ho appena aggiornato il jsFiddle per ordinare da .attr() e sembra funzionare. http://jsfiddle.net/VQu3S/9/ –

-3

Vorrei ottenere il .text() di ciascun elemento abeti, poi messo su un array , ordina l'array, quindi sposta ciascun elemento in cui gli indici di SORTED corrispondono a UNSORTED.

e io sono troppo pigro per scrivere il codice per questo e testarlo in questo momento :) ma solo un pensiero del mio modo di affrontarlo.