Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   сценарий замедляет работу IE (https://javascript.ru/forum/jquery/8218-scenarijj-zamedlyaet-rabotu-ie.html)

Shaci 15.03.2010 14:09

сценарий замедляет работу IE
 
есть скрипт, в FF и Opera работает, а в IE вылетает
A script on this page is causing Internet Explorer to run slowly и.т.д.

понимаю, телепаты в отпуске, но не кажется, есть целый "класс" таких скриптов, которые нормально работают в FF, но глючат в IE,
определенно, что-то одно их должно объединять.

возможно, кто-то встречался с такой проблемой?
скорее всего в таких скриптах дело в циклах?

e1f 15.03.2010 15:13

скорее всего дело в руках...
да, и телепаты действительно в отпуске :)

subzey 15.03.2010 15:15

Да, в принципе, ничего необычного. jQuery замедляет работу IE, а IE заменяет работу jQuery.

e1f 15.03.2010 15:33

subzey, то же самое можно сказать и о Javascript в целом, относительно ИЕ.
Вообще неожиданные циклы могут появлятся из-за "лавинообразного" наступления событий: в частности, с чем-то подобным я сталкивался при использовании jQuery.resize биндов в ИЕ.

Shaci 15.03.2010 15:44

да там у меня просто много много option в select, каждый обрабатывается с jquery, если их мало, то тормозов нет, похоже дело в этом

e1f 15.03.2010 15:48

Shaci, приведите рабочий фрагмент кода, который работает медленно.

Kolyaj 15.03.2010 16:05

Есть у нас один скриптик (запускается только в Firefox), который пробегается по DOM-дереву всяких разных страничек и сохраняет всякие параметры каждого узла. Так вот, попалась страничка, на которой было порядка 3000 option'ов. На такой страничке скрипт выполнялся около 2-х минут (тут нет опечатки). К слову 3000 любых других элементов обрабатываются доли секунды.

Мораль ищите сами. Я в скрипте тупо исключил обработку options, они мне не важны.

Пользователю, кстати, много option'ов тоже не нужны.

subzey 15.03.2010 16:32

e1f,
Reflow — вообще, штука опасная в плане производительности.

Kolyaj,
спасибо, пока с подобным не сталкивался, но при случае буду готов.

Shaci 15.03.2010 16:38

Если вкратце, есть плагин, он небольшой:
http://plugins.jquery.com/project/De...SelectbySilVeR
зависимых селектов, в котором зависимость одного селекта от другого указывается на основе tilte родителя, и class зависимого селекта.
В зависимости от того, что кидается ему внутрь, может работать в двух режимах.Когда несколько селектов зависят от одного, и когда зависимость по цепочке.

Я переделал его так, чтобы зависимость была не на основе title и class, а на основе value "опшионов", но это не важно.
Так вот. там есть ф-ция (практически не менял ее):
function _createHolder($holder, $holder_cls, $child, $child_id, $child_cls){		
		var $is_created = $($holder_cls+' '+$child_id).size();                
		if( $is_created == 0 ){
			$('body').append('\n\n<select class="'+$holder+' '+$child_id+'" style="display:none">\n</select>\n');
		}        
		$($child).find('option:not(:first)').each(function(){         
			$value = $(this).attr('value');
			$class = $(this).attr('class');
			$title = $(this).attr('title');
			$text  = $(this).text();
			$($holder_cls+$child_cls).append('<option    value="'+$value+'" class="'+$class+'" title="'+$title+'">'+$text+'</option>\n');
		});
            //$child - зависимый селект
            // $($holder_cls+$child_cls) - его скрытый

которая создает для каждого зависимого селекта скрытый селект (селект-хранилище),
в который складываются все option зависимого селекта, потом, по выбору определенных option из родительского селекта к зависимому из его скрытого добавляются соответствующие option.
Так вот: эта строчка
$($holder_cls+$child_cls).append('<option value="'+$value+'" class="'+$class+'"title="'+$title+'">'+$text+'</option>\n');

приводит к тому, что IE виснет, если в зависимом select много много option будет, видимо потому, что создается целая куча элементов option.

e1f 15.03.2010 16:48

Возможно, стоит переписать не скучей аппендов, а с использованием DocumentFragment

subzey 15.03.2010 17:56

Мне кажется, достаточно будет вынуть из документа select. А, если точнее, не вставлять его в документ, пока все манипуляции не будут окончены. Да и вообще, не лучше ли формировать из этого массив, а потом одним куском вставить в innerHTML?

Shaci 15.03.2010 18:05

Цитата:

Сообщение от e1f (Сообщение 47748)
Возможно, стоит переписать не скучей аппендов, а с использованием DocumentFragment

Спс , помогло, но дальше на обработчике событий проблема та же, в принципе это ожидалось ((
function _parentChange($parent, $child, $group, $holder_cls, $child_cls, i){
		$($parent).bind('change', function(vary){return function(){
			$($child).find('option:not(:first)').remove();            
			$index = $($group).index($(this));    			
			if( $param.group != '' ){                
                $($group+':gt('+ $index +')').find('option:not(:first)').remove();
			}
			$value = $(this).find('option:selected').attr('value');

            if($value) {
            if(vary[i][$value]){
            for(var j = 0; j < vary[i][$value].length; j++) {
			$($holder_cls+$child_cls).find('option[value='+vary[i][$value][j]+']').each(function(){
				$value1 = $(this).attr('value');
				$class = $(this).attr('class');
				$title = $(this).attr('title');
				$text  = $(this).attr('text');
				$($child).append('<option value="'+$value1+'" class="'+$class+'" title="'+$title+'">'+$text+'</option>');
			});
            }
            }
            }
            $($child).change();
        }
		}($param.myObj));
	}


он переписан мной (может конешн и криво написан, но работает, учитывает оба режима плагина)
Обработчик change на родителе ищет option в скрытом селекте и кидает их в соостветствующий ему дочерний селект .
Так вот этот процесс поиска в IE занимает много времени, и здесь, похоже уже ничего не сделать.
Вот эта строка:
$($holder_cls+$child_cls).find('option[value='+vary[i][$value][j]+']').each(function(){
тянет время, даже если в цикле пусто,
если закомменчю её, то все ОК(по скорости).

e1f 15.03.2010 18:43

Охтыжепт.
1. Цикл for убрать, это можно сделать одной выборкой + each.
2. Внутри each не делать 4 раза создание jQuery-объекта и запрос атрибута.
3. Если не нужно заполнять существующий select, то имеет смысл, как уже сказал subzey, сделать все через innerHTML. Добавить опшны в селект через innerHTML не выйдет -- персональный бок ИЕ.

Shaci 16.03.2010 00:12

Цитата:

Сообщение от e1f (Сообщение 47768)
Охтыжепт.

-ну, да :), но я пока учусь
Цитата:

Сообщение от e1f;
2. Внутри each не делать 4 раза создание jQuery-объекта и запрос атрибута.

- не поможет, в данном случае это несильно повлияет
тутс вложенный цикл
for(var j = 0; j < vary[i][$value].length; j++) {
			$($holder_cls+$child_cls).find('option[value='+vary[i][$value][j]+']')

долго выполняется

e1f 16.03.2010 01:14

А если вместо всего for'a сделать просто
$($holder_cls+$child_cls+' > option').each() // ...

Ну и, как уже упоминалось -- либо пересоздавать весь скрытый селект заново с помощью innerHTML, либо использовать DocumentFragment.

Shaci 16.03.2010 21:26

Вложений: 1
for убрать,наверно не получится
Дело в том, что:
Цитата:

Если вкратце, есть плагин, он небольшой:
http://plugins.jquery.com/project/De...SelectbySilVeR
зависимых селектов, в котором зависимость одного селекта от другого указывается на основе tilte родителя, и class зависимого селекта.
В зависимости от того, что кидается ему внутрь, может работать в двух режимах.Когда несколько селектов зависят от одного, и когда зависимость по цепочке.
Т.е. было так:
$('#child_id').dependent({ parent: 'parend_id', group: 'common_class' });
<b>My case</b>
$('#selectme2').dependent({ parent: 'selectme', group: 'selectable' });
$('#selectme3').dependent({ parent: 'selectme2', group: 'selectable' });

Для зависимости "по цепочке"
И так
$('#child_id').dependent({ parent: 'parend_id' });
<b>My case</b>
$('#selectme4, #selectme5').dependent({ parent: 'selectme3' });

при зависимости кучи селектов от одного , ну и + необходимо было указывать title и class у этих селектов.

Цитата:

Я переделал его так, чтобы зависимость была не на основе title и class, а на основе value "опшионов"
И теперь при запуске в режиме, когда от одного зависят все:
<script type="text/javascript" src="jquery-1.4.1.js"></script>
<script type="text/javascript" src="jquery.myDepend.js"></script>

<style>
    .selectable{width:60}
</style>

<script type="text/javascript">
    jQuery(function($){$("#selectme1,#selectme2").dependent({parent:"selectme", myObj:'[{"0":[7,107,13],"3":[7,107],"6":[13]},{"0":[1000,68,1100],"3":[1000,68],"6":[1100]}]'}); $("#selectme").change();
    });
    </script>
<select name="selectme" id="selectme" class="selectable">
    <option value="0"></option>
    <option value="3" selected="selected">Opt3</option>

    <option value="6">Opt6</option>
</select>

<select name="selectme1" id="selectme1" class="selectable">
    <option value="0"></option>
    <option value="7">Opt3</option>
    <option value="107">Opt3</option>
    <option value="13">Opt6</option>

</select>

<select name="selectme2" id="selectme2" class="selectable">
    <option value="0"></option>
    <option value="1000">Opt3</option>
     <option value="68">Opt3</option>
    <option value="1100">Opt6</option>
</select>


И параметр myObj, как раз и указывает эти зависимости:
myObj:'[{"0":[7,107,13],"3":[7,107],"6":[13]},{"0":[1000,68,1100],"3":[1000,68],"6":[1100]}]'
Т.е. при Value 0 у родителя, выбрать option с value 7, 107, 13 у первого
селекта, и 1000, 68, 1100 у второго. и.т.д.

и в случае зависимости по цепочке:
<script type="text/javascript" src="jquery-1.4.1.js"></script>
<script type="text/javascript" src="jquery.myDepend.js"></script>

<style>
    .selectable{width:60}
</style>

<script type="text/javascript">
    jQuery(function($){$("#selectme1").dependent({parent:"selectme", myObj:'[[[0,2,4,7,8,9],[2,4,7],[8,9]]]', group:"selectable"});$("#selectme2").dependent({parent:"selectme1", myObj:'[{"0":[0,5,6,7,29],"2":[5],"4":[5],"7":[5],"8":[7,6],"9":[29]}]', group:"selectable"});$("#selectme").change();
    });
    </script>
<select name="selectme" id="selectme" class="selectable">
    <option value="0"></option>
    <option value="1">Opt1</option>

    <option value="2">Opt2</option>
</select>

<select name="selectme1" id="selectme1" class="selectable">
    <option value="0"></option>
    <option value="2">Opt1</option>
    <option value="4">Opt1</option>
    <option value="7">Opt1</option>

    <option value="8">Opt2</option>
    <option value="9">Opt2</option>
</select>

<select name="selectme2" id="selectme2" class="selectable">
    <option value="0"></option>
    <option value="5">Opt247</option>
    <option value="6">Opt8</option>

    <option value="7">Opt8</option>
    <option value="29">Opt9</option>
</select>

$("#selectme1").dependent({parent:"selectme", myObj:'[[[0,2,4,7,8,9],[2,4,7],[8,9]]]', group:"selectable"}:
Здесь, при выборе у selectme option c value 0 у selectme1 выберутся 0,2,4,7,8,9
при 1 - 2,4,7 , ну и.т.д.
Причем метод может получать myObj как в виде массива массивов (как выше)
так и в виде массива объектов, как ниже
$("#selectme2").dependent({parent:"selectme1", myObj:'[{"0":[0,5,6,7,29],"2":[5],"4":[5],"7":[5],"8":[7,6],"9":[29]}]', group:"selectable"}
Связанно это с тем, что
<script type="text/javascript">
    jQuery(function($){$("#selectme1").dependent({parent:"selectme", myObj:'[[[0,2,4,7,8,9],[2,4,7],[8,9]]]', group:"selectable"});$("#selectme2").dependent({parent:"selectme1", myObj:'[{"0":[0,5,6,7,29],"2":[5],"4":[5],"7":[5],"8":[7,6],"9":[29]}]', group:"selectable"});$("#selectme").change();
    });
    </script>
этот кусок генерится php ф-цией, в которую входит ф-ция array2json, которой,на вход поступает php массив, сгенерированный на основе запросов из базы данных,( и она в зависимости от того как в массиве идут индексы, по порядку, или нет, может создавать либо массив массивов, либо массив объектов).
Но это не важно.

А по поводу вложенных циклов:
for(var j = 0; j < vary[i][$value].length; j++) {
$($holder_cls+$child_cls).find('option[value='+vary[i][$value][j]+']')
- это нужно, чтобы шагать по myObj, и находить соответствия между option селектов, пока optionов не много то все нормально, но когда их с тысячу и больше, тормозит в IE.

i - это элемент массива myObj (массив или объект), показывающий зависимость дочернего селекта от родительского (в случае зависимости по цепочке - single, i - всегда 0)
$value - текущее value выбранного option(у родительского элемента), и элемент i-го массива,
его элементы - value тех option, которые должны будут выбраны

Похоже, тут вообще линейный поиск по неупорядоченному массиву получается
, хотел отсортировать и производить поиск по сортированному массиву, но сортировка в IE занимает еще больше места
Как вариант табличку повесить, подождите, идет загрузка)).

Здесь плагин (без documentFragment) если вдруг интересно станет (более месяця назад его делал, так что, возможно, многое можно поменять, но он рабочий)

Shaci 17.03.2010 19:15

Переписал плагин по другому принципу и избавился от вложенных циклов, не тормозит.:dance:


Часовой пояс GMT +3, время: 02:22.