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

2

7

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

Crissman answered 16/11, 2010 at 15:37 Comment(4)
I've poured through that code and it should take that long. Do you know if it's capping system resources or something else?Spermophyte
Now, this is going to shock you, but IE's JavaScript performance is slow/poor.Memorabilia
bottom line: IE is slow. Frankly I'd leave it at that; it makes a good incentive for people to upgrade if they have obvious evidence that their browser sucks. (in all seriousness, I know that's probably not an option, and you have been given a working solution, but in cases where it's marginal my opinion is just let the IE users suffer)Edwin
Outside Of IE9, what does IE do with e.preventDefault()?Malia
D
4

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

Dev answered 16/11, 2010 at 15:42 Comment(0)
J
2

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.

Jolenejolenta answered 16/11, 2010 at 15:50 Comment(2)
Yes, I need to allow for multiple selected items. It very well could be the UI layer trapping me. Are you saying I should run the function with a timer?Crissman
You run some code, then use setTimeout to call the next chunk of code. setTimeout will let the IE UI update, then call you. See: #788000Jolenejolenta

© 2022 - 2024 — McMap. All rights reserved.