2012-02-25 9 views
6

Ho una lista 'sorgente' non ordinata che può contenere fino a circa 1.000 voci di elenco. Voglio essere in grado di trascinare gli elementi dall'elenco sorgente in una lista 'destinazione' connessa. Ho tutto funzionante fino a quando il mio elenco di fonti non viene filtrato. Sto usando il plug-in quicksearch di jquery per filtrare (cercare) la mia lista di fonti. Il filtro si ottiene impostando 'display: none;' sugli articoli che non corrispondono alla ricerca.jQuery UI L'avvio di trascinamento ordinabile è lento quando il contenitore ha oggetti nascosti

Quando 1..n elementi nell'elenco di origine sono nascosti, l'operazione di trascinamento non è fluida quando avviata. Significato, clicco sulla voce che voglio trascinare, muovo il mio mouse sullo schermo, ma l'oggetto che sto trascinando non appare sotto il mio cursore fino a circa un secondo dopo che ho iniziato il trascinamento.

Per la diagnosi, ho ridotto il mio caso di utilizzo a una sola lista che voglio ordinare. Ho completamente eliminato l'uso della ricerca rapida semplicemente codificando la metà dei miei elementi di elenco come nascosti. Sono ancora in grado di riprodurre il comportamento 'non fluido'. Il mio esempio è qui:

http://pastebin.com/g0mVE6sc

Se rimuovo lo stile di trabocco dalla lista nel mio esempio, la prestazione è un po 'meglio, ma ancora più lento di quanto mi auguro di vedere.

Qualcuno ha qualche suggerimento per me prima di iniziare a considerare altre opzioni?

Grazie in anticipo.

risposta

11

Come si può vedere su questo jsferf esempio, calcolare outerWidth()/outerHeight() (questo è ciò che il plugin fa - vedi sotto) per gli elementi nascosti (con display nessuno) è terribilmente lento rispetto per gli elementi visibili, se è ottenuto da un attributo di stile o una classe.

L'unico modo che ho trovato per aggirare questo e ancora ottenere lo stesso risultato è quello di impostare l'altezza per gli elementi di nascondere a zero, invece di lavorare con la proprietà di visualizzazione, sia che si utilizzi l'atttibute stile o di una classe :

<li style="height: 0;">b</li> 
<li class="hidden">b</li> 

.hidden { height: 0 } 

DEMO (with class) - DEMO (with style attr)


Cosa sta succedendo con ordinabile durante il trascinamento di un elemento?

All'avvio del trascinamento, il plug-in aggiorna l'elenco di tutti gli elementi e ricalcola le posizioni di tutti gli elementi. Il plugin in realtà ottiene outerWidth e outerHeight:

_mouseStart: function(event, overrideHandle, noActivation) { 
    ... 
    //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 
    this.refreshPositions(); 
    ... 
} 

refreshPositions: function(fast) { 
    ... 
    for (var i = this.items.length - 1; i >= 0; i--) { 
     var item = this.items[i]; 
     ... 
     if (!fast) { 
      item.width = t.outerWidth(); 
      item.height = t.outerHeight(); 
     } 
     var p = t.offset(); 
     item.left = p.left; 
     item.top = p.top; 
    }; 
    ... 
    return this; 
},​ 
+0

il fix ha funzionato perfettamente, grazie mille! – podnov

6

Se si desidera continuare a utilizzare display: none, questo è una semplice correzione alla fonte jQuery UI specificato nella risposta di Didier:

if (!fast) { 
    if(item.item.css('display') === 'none') { 
     item.width = 0; 
     item.height = 0; 
    } 
    else { 
     item.width = t.outerWidth(); 
     item.height = t.outerHeight(); 
    } 
} 

Questo è il mio primo post su StackOverflow, quindi fammi sapere se ho incasinato qualcosa.

5

Avevo anche un problema simile, ma con contenitori a caduta nascosti anziché elementi ordinabili.Ecco la mia soluzione applicando la risposta di Jordan agli oggetti ordinabili e ai loro contenitori e semplicemente sostituendo il metodo di recupero.

$.ui.sortable.prototype.refreshPositions = function(fast) { 
    //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 
    if(this.offsetParent && this.helper) { 
     this.offset.parent = this._getParentOffset(); 
    } 

    for (var i = this.items.length - 1; i >= 0; i--){ 
     var item = this.items[i]; 

     //We ignore calculating positions of all connected containers when we're not over them 
     if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) 
      continue; 

     var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 

     if (!fast) { 
      /********** MODIFICATION ***********/ 

      if(item.item.css('display') === 'none') { 
       item.width = 0; 
       item.height = 0;      
      } else { 
       item.width = t.outerWidth(); 
       item.height = t.outerHeight(); 
      } 

      /********** END MODIFICATION ***********/ 
     } 

     var p = t.offset(); 
     item.left = p.left; 
     item.top = p.top; 
    }; 

    if(this.options.custom && this.options.custom.refreshContainers) { 
     this.options.custom.refreshContainers.call(this); 
    } else { 
     for (var i = this.containers.length - 1; i >= 0; i--){ 

      /********** MODIFICATION ***********/ 

      if (this.containers[i].element.css('display') == 'none') { 
       this.containers[i].containerCache.left = 0; 
       this.containers[i].containerCache.top = 0; 
       this.containers[i].containerCache.width = 0; 
       this.containers[i].containerCache.height = 0; 
      } else { 
       var p = this.containers[i].element.offset(); 
       this.containers[i].containerCache.left = p.left; 
       this.containers[i].containerCache.top = p.top; 
       this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 
       this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 
      } 

      /********** END MODIFICATION ***********/ 
     }; 
    } 

    return this; 
}; 
+0

fantastico! questo ha risolto il mio problema simile. –

1

mi sono imbattuto con lo stesso problema ... Ho cercato una soluzione, ma sembra non v'è alcuna soluzione al problema jquery, solo un po 'di soluzione ... non ho trovato o una soluzione, solo un'altra soluzione.

Nel mio caso ho appena creato un metodo generale per una ricerca in un elenco ordinabile, dove su keyup, il codice va e fa una ricerca su ogni elemento nell'elenco e lo nascondeva per dissolvenza se non corrispondeva il valore. Stava funzionando molto bene, ma quando hai centinaia di elementi in una lista, quella di hidden diventa abbastanza grande da innescare l'effetto lento sul rilascio del trascinamento &. La mia soluzione era quella di riordinare l'elenco, portando verso l'alto le voci corrispondenti .. Basta rimuovere e appendTo di nuovo ...

In questo modo non ho problemi con gli elementi nascosti :)

Spiacente questo non era una soluzione, ma solo un'altra soluzione ..

saluti

+0

Più recentemente mi sono imbattuto di nuovo in questo problema ... e ho scoperto che la mia soluzione alternativa non era più la soluzione migliore. –

1

Più di recente ho mai incontrato questo problema ancora una volta ... e ha scoperto che la mia soluzione non era più la soluzione migliore. Dal momento che il problema è l'altezza ... ho appena creare una classe CSS con

.hidden {display: block; line-height:0; height: 0; overflow: hidden; padding: 0; margin: 0; }

e invece di impostare l'elemento nascosto con solo aggiungere questa classe e rimuoverlo per mostrare/nascondere l'elemento ..

saluti, AP

+0

Funziona alla grande! Grazie per aver pubblicato una soluzione CSS! – lucusp

+0

Ho aggiunto 'width: 0; confine: 0' – lucusp

Problemi correlati