2010-11-16 8 views
7

Pracuję nad utworzeniem listy wielokrotnego wyboru, w której można wybrać elementy, a następnie kliknąć przycisk "W górę" lub "W dół", co pozwoli zmienić kolejność pozycji na liście.Dlaczego ten javascript działa tak wolno w IE, gdy wszystko, co robi, modyfikuje listę wyboru?

Mam proste samodzielne przykład:

<html> 
    <head> 
     <title>Example</title> 
    <script src="https://www.google.com/jsapi"></script> 
    <script> 
     google.load('jquery', '1.4.1'); 
    </script> 
    </head> 
    <body> 
     <select id="selectedDataPoints" multiple="multiple"> 
      <option>Pig</option> 
      <option>Duck</option> 
      <option>Dog</option> 
      <option>Zebra</option> 
      <option>Snake</option> 
      <option>Giraffe</option> 
      <option>Cow</option> 
     </select> 
    <input type="button" id="btnReorderUp" value="Up" /> 
    <input type="button" id="btnReorderDown" value="Down" /> 
    </body> 
</html> 

<script type="text/javascript"> 
    var DataPointSelector = (function() { 

    var $selectedList = $('#selectedDataPoints'); 

     $('#btnReorderUp').click(function(e) { 
      moveUp(); 
      e.preventDefault(); 
     }); 

     $('#btnReorderDown').click(function(e) { 
      moveDown(); 
      e.preventDefault(); 
     }); 

    function moveUp() { 
      var select = $selectedList[0]; 
      for (var i = 1, n = select.options.length; i < n; i++) 
       if (select.options[i].selected && !select.options[i - 1].selected) 
       select.insertBefore(select.options[i], select.options[i - 1]); 
     } 

     function moveDown() { 
      var select = $selectedList[0]; 
      for (var i = select.options.length - 1; i > 0; i--) 
       if (select.options[i].selected && !select.options[i + 1].selected) 
        select.insertBefore(select.options[i + 1], select.options[i]);   
     } 

    }()); 
</script> 

Jednak przycisk W górę/W dół trwa dosłownie 3-8 sekund odniosły skutek w IE7/8. Pierwsze kliknięcie będzie czasami szybkie, ale potem bardzo długo zajmuje aktualizację listy wyboru z nowymi pozycjami (szczególnie, jeśli wybrano kilka pozycji).

Ten problem nie występuje w przeglądarce Chrome/FF. Nie sądziłbym, że tak proste uporządkowanie będzie tak intensywne!

Czy ktoś ma jakieś informacje, które mogłyby zostać wykorzystane do przyspieszenia funkcji moveUp/moveDown ?!

+0

Przelałem ten kod i to powinno zająć tyle czasu. Czy wiesz, czy to ogranicza zasoby systemu, czy coś innego? –

+0

Teraz to cię zaszokuje, ale wydajność JavaScriptu IE jest wolna/słaba. – Powerlord

+0

dolny wiersz: IE jest wolny. Szczerze mówiąc, zostawiłbym to; to dobry bodziec dla ludzi do aktualizacji, jeśli mają oczywiste dowody na to, że ich przeglądarka jest do bani. (z całą powagą, wiem, że to prawdopodobnie nie jest opcja, a ty dostałeś działające rozwiązanie, ale w przypadkach, w których jest to marginalne, moim zdaniem jest po prostu pozwól użytkownikom IE cierpieć) – Spudley

Odpowiedz

4

Zamiast przenosić istniejące elementy DOM, odtworzyć cały element <select>, w tym wszystkie elementy podrzędne dla IE.

2

IE jest powolny, powolny, wolny. Powinieneś więc sprawdzić kod, aby zminimalizować niepotrzebne operacje.

@Arron Digulla's idea jest dobra. Ale możesz także zminimalizować czas procesora, wprowadzając następujące zmiany:

function moveUp() { 
    var select = $selectedList[0]; 
    for (var i = 1, n = select.options.length; i < n; i++) 
    var selected = select.options[i], 
     selectedPrior = select.options[i - 1]; 
     // Don't locate obj/array element more than once 
    if (selected.selected && !selectedPrior.selected) { 
     select.insertBefore(selected, selectedPrior); 
     break; // Since we have found the right elements, don't do 
    }  // any further checking 
    } 

Dodano: Hmmm, teraz widzę, że można wybrać wiele przedmiotów. Więc musisz przenieść wiele przedmiotów, tak? W takim przypadku instrukcja break nie jest właściwa.

Czy warstwa IE UI Cię łapie? - IE nie aktualizuje wyglądu ekranu, dopóki wątek JS nie zostanie zakończony. Obejście polega na uruchomieniu timera za pomocą 0 s. To przyniesie silnik renderowania IE i umożliwi aktualizację ekranu.

+0

Tak, muszę zezwolić na wiele wybranych elementów. Bardzo dobrze może być warstwa UI mnie uwięziona. Mówisz, że powinienem uruchomić funkcję za pomocą timera? – Markus

+0

Uruchomiony kod, a następnie użyj setTimeout do wywołania następnego fragmentu kodu. setTimeout pozwoli aktualizacji IE UI, a następnie zadzwoń do ciebie. Zobacz: http://stackoverflow.com/questions/787500/why-is-jquery-ajax-so-slow-on-ie-ie7/787568#787568 –