2010-11-16 1 views
7

Я работаю над тем, чтобы иметь список с несколькими выборами, в котором вы можете выбрать элементы, а затем нажать кнопку «Вверх» или «Вниз», что позволит вам изменить порядок этих элементов в списке.Почему этот javascript работает так медленно в IE, когда все это делает, это изменить список выбора?

У меня есть простой автономный пример:

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

Однако кнопка вверх/вниз занимает буквально 3-8 секунд, чтобы вступить в силу в IE7/8. Первый клик иногда будет быстрым, но после этого требуется, чтобы список выбора обновлялся с новыми позициями (особенно, если у вас выбрано несколько элементов).

Эта проблема отсутствует в Chrome/FF. Я бы не подумал, что это простое переупорядочение будет настолько интенсивным!

Есть ли у кого-нибудь информация, которая могла бы помочь мне ускорить функции moveUp/moveDown ?!

+0

Я вылил этот код, и это займет столько времени. Знаете ли вы, что это ограниченные системные ресурсы или что-то еще? –

+0

Теперь это вас шокирует, но производительность JavaScript IE медленная/бедная. – Powerlord

+0

нижняя строка: IE медленный. Честно говоря, я оставил бы это; это создает хороший стимул для людей обновляться, если у них есть очевидные доказательства того, что их браузер отстой. (во всей серьезности, я знаю, что это, вероятно, не вариант, и вам дано рабочее решение, но в тех случаях, когда это мое мнение просто позволяет пользователям IE страдать) – Spudley

ответ

4

Вместо того, чтобы перемещать существующие элементы DOM вокруг, воссоздайте весь элемент <select>, включая всех детей для IE.

2

IE медленный, медленный, медленный. Поэтому вы должны проверить свой код, чтобы свести к минимуму ненужные операции.

@ Идея Аррона Дигуллы хорошая. Но также можно свести к минимуму времени процессора следующих изменений:

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 
    } 

Добавлено: Ммм, я теперь вижу, что множественные элементы могут быть выбраны. Итак, вам нужно переместить несколько элементов, да? В этом случае оператор break не прав.

Является ли IE UI-слоем вас? - IE не обновляет внешний вид экрана до тех пор, пока поток JS не завершится. Обходной путь - запустить таймер с 0 сек. Это приведет к движку рендеринга IE и включит экран для обновления.

+0

Да, мне нужно разрешить несколько выбранных элементов. Это очень хорошо может быть слоем UI, улавливающим меня. Вы говорите, что я должен запустить функцию с помощью таймера? – Markus

+0

Вы запускаете некоторый код, а затем используете setTimeout для вызова следующего фрагмента кода. setTimeout позволит обновить IE UI, а затем вызовет вас. См .: http://stackoverflow.com/questions/787500/why-is-jquery-ajax-so-slow-on-ie7/787568#787568 –