7

我正在制作一个多选列表,您可以在其中选择项目,然后单击“向上”或“向下”按钮,您可以在列表中重新排序这些项目。

我有一个简单的独立示例:

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

但是,在 IE7/8 中,Up/Down 按钮实际上需要 3-8 秒才能生效。第一次单击有时会很快,但之后选择列表需要很长时间才能更新为新位置(特别是如果您选择了几个项目)。

Chrome/FF 中不存在此问题。我不会想到这个简单的重新排序会如此密集!

有没有人有任何信息可以用来帮助我加快 moveUp/moveDown 功能?!

4

2 回答 2

4

与其移动现有的 DOM 元素,不如重新创建整个<select>元素,包括 IE 的所有子元素。

于 2010-11-16T15:42:57.353 回答
2

IE 很慢,很慢,很慢。因此,您应该检查您的代码以尽量减少不必要的操作。

@Arron Digulla 的想法很好。但您也可以通过以下更改最小化处理器时间:

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 层困住了你吗?-- 在 JS 线程结束之前,IE 往往不会更新屏幕的外观。解决方法是以 0 秒运行计时器。这将让给 IE 渲染引擎并使屏幕能够更新。

于 2010-11-16T15:50:53.623 回答