Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this javascript run so slow in IE when all it does is modify a select list?

I'm working on having a multi-select list where you can have items selected and then click an "Up" or "Down" button that will allow you to reorder those items within the list.

I've got a simple self-contained example:

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

However, the Up/Down button takes literally 3-8 seconds to take effect in IE7/8. The first click will sometimes be fast but after that it takes a very long time for the select list to update with the new positions (especially if you have a couple items selected).

This problem is not present in Chrome/FF. I wouldn't have thought this simple reordering would be so intensive!

Does anyone have any information that could be used to help me speed the moveUp/moveDown functions?!

like image 316
Markus Avatar asked Nov 16 '10 15:11

Markus


2 Answers

Instead of moving the existing DOM elements around, recreate the whole <select> element including all children for IE.

like image 161
Aaron Digulla Avatar answered Oct 09 '22 09:10

Aaron Digulla


IE is slow, slow, slow. So you should check your code to minimize unneeded operations.

@Arron Digulla's idea is good. But also you could minimize processor time by the following changes:

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
  }

Added: Hmmm, I now see that multiple items can be selected. So you then need to move multiple items, yes? In that case the break statement is not right.

Is the IE UI layer trapping you? -- IE tends not to update the screen's appearance until the JS thread has ended. The workaround is to run the timer with 0 sec. That will yield to the IE rendering engine and enable the screen to update.

like image 40
Larry K Avatar answered Oct 09 '22 09:10

Larry K