对选择了多个选项的select元素进行排序会反转顺序

时间:2015-10-25 03:50:19

标签: javascript html sorting select

我有一个包含很长人名的select元素。我希望能够在列表中选择多个人,并通过单击箭头对其进行上下排序。我以为我得到了它的工作,但每次我移动一个选择,所选的选项按顺序颠倒。

这就像第二个选择的选项向上移动并且也移动到第一个...不确定发生了什么。提前谢谢!

var select = _select;
var optionsNodeList = select.options;
var options = [];
var selectedIndexes = [];

for (var i = 0; i < optionsNodeList.length; i++) {
    var option = optionsNodeList.item(i);
    options.push(option);
    if (option.selected) {
        selectedIndexes.push(i);
    }
}

var len = selectedIndexes.length;
var firstSelected = selectedIndexes[0];
var lastSelected = selectedIndexes[len-1];
if (isSortUp === true && firstSelected !== 0) {
    for (var i = 0, currIndex; i < len; i++) {
        var currIndex = selectedIndexes[i];
        insertBefore(options[currIndex], options[currIndex-1]);             
    }
} else if (isSortUp === false && lastSelected !== options.length-1) {
    for (var i = len-1, currIndex; i > -1; i--) {
        var currIndex = selectedIndexes[i];
        insertAfter(options[currIndex], options[currIndex+1]);
    }
}

function insertBefore(newNode, refNode) {
    refNode.parentNode.insertBefore(newNode, refNode);
}
function insertAfter(newNode, refNode) {
    refNode.parentNode.insertBefore(newNode, refNode.nextSibling);
}

在按向上箭头之前: before screen shot 按下向上箭头后: after screen shot

2 个答案:

答案 0 :(得分:2)

您的错误是您将选项放在上一个选项之前,因此第二个选项&#34; insertBefore&#34;第一个。

实施例: 选项1 - 索引0 选项2(选定) - 索引1 选项3(选定) - 索引2

在索引0之前的第一个选定插入即可,secod选择在索引1之前插入,因此它在索引1的顶部,不是很好。

你可以做这样的事情来解决你的问题。

if (isSortUp === true && firstSelected !== 0) {
    for (var i = 0, currIndex; i < len; i++) {
        var currIndex = selectedIndexes[i];
        if(i == 0){
          insertBefore(options[currIndex], options[currIndex-1]);             
        }else{
          insertAfter(options[currIndex], options[currIndex-1]); 
        }
    }
} 

使用第一个选定的插入位于前一个插入之前,所选的其余部分放在第一个选定位置之后。

答案 1 :(得分:0)

根本不需要循环。而不是移动整个组,只需在(或之后)之前移动选项:

if (isSortUp === true && firstSelected !== 0) {
    insertAfter(options[firstSelected - 1], options[lastSelected]);
} else if (isSortUp === false && lastSelected !== options.length-1) {
    insertBefore(options[lastSelected + 1], options[firstSelected]);
}

但是,为了完整性,您的订单被交换的原因是您在循环中重新排序DOM中的元素,但是您没有重新排序您拥有的数组options。您不必使用此额外数组来存储选项。如果您将代码更改为直接使用select.options,则代码将在您编写代码时实际运行,而无需在每次点击时重新排序所选选项。

document.getElementById("up").addEventListener("click", function(){
    move(true);
});
document.getElementById("down").addEventListener("click", function(){
    move(false);
});

function move(isSortUp){
    var select = document.getElementById("sel");
    var optionsNodeList = select.options;
    var options = [];
    var selectedIndexes = [];

    for (var i = 0; i < optionsNodeList.length; i++) {
        var option = optionsNodeList.item(i);
        options.push(option);
        if (option.selected) {
            selectedIndexes.push(i);
        }
    }

    var len = selectedIndexes.length;
    var firstSelected = selectedIndexes[0];
    var lastSelected = selectedIndexes[len-1];
    
    if (isSortUp === true && firstSelected !== 0) {
        insertAfter(options[firstSelected - 1], options[lastSelected]);
    } else if (isSortUp === false && lastSelected !== options.length-1) {
        insertBefore(options[lastSelected + 1], options[firstSelected]);
    }
}

function insertBefore(newNode, refNode) {
    refNode.parentNode.insertBefore(newNode, refNode);
}
function insertAfter(newNode, refNode) {
    refNode.parentNode.insertBefore(newNode, refNode.nextSibling);
}
<select id="sel" multiple="multiple" style="width: 100px; height: 150px;">
    <option>a</option>
    <option>b</option>
    <option>c</option>
    <option>d</option>
    <option>e</option>
    <option>f</option>
    <option>g</option>
    <option>h</option>
    <option>i</option>
    <option>j</option>
</select>
<button id="up">up</button>
<button id="down">down</button>

http://jsfiddle.net/9v32xs0o/