我试图创建一个双列表框使用只有香草Javascript, 没有JQuery或JS包,用于学习。
当用户双击一个Option时,该Option追加到另一个父Select (boxB),并从原始父Select (boxA)中删除,反之亦然。Option元素具有数字升序的数据索引属性。如何根据索引值维护选项的数字顺序,而不管它们附加哪个父Select ?
<!-- HTML -->
<select id="ctst1" class="form-control form-control-sm" size="8" multiple>
<option data-index="1" value="CPT">CPT</option>
<option data-index="2" value="SST">SST</option>
<option data-index="3" value="EDTA">EDTA</option>
<option data-index="4" value="PAXgene">PAXgene</option>
<option data-index="5" value="NP SWB">NP SWB</option>
<option data-index="6" value="OP SWB">OP SWB</option>
<option data-index="7" value="RCTL SWB">RCTL SWB</option>
<option data-index="8" value="Self NS">Self NS</option>
</select>
<select id="ctst2" class="form-control form-control-sm" size="8" multiple></select>
// Javascript
const dataFrame = {
"selCollTubeSampTypes": [
["CPT", "CPT"],
["SST", "SST"],
["EDTA", "EDTA"],
["PAXgene", "PAXgene"],
["NP SWB", "NP SWB"],
["OP SWB", "OP SWB"],
["RCTL SWB", "RCTL SWB"],
["Self NS", "Self NS"]
]
};
function dualListBox(qryId1, qryId2, dataset) {
const boxA = document.getElementById(qryId1);
const boxB = document.getElementById(qryId2);
// Populate avail box with data
for (let i = 0; i < dataset.length; i++) {
const eleOption = document.createElement("option");
eleOption.dataset.index = i + 1; // Adds data-index value to Option node
if (dataset[i][0] === "") {
eleOption.textContent = dataset[i][1];
} else {
eleOption.value = dataset[i][0];
eleOption.textContent = dataset[i][1];
};
boxA.appendChild(eleOption);
};
// When option in Box A is double-clicked, move it to Box B
boxA.addEventListener("dblclick", e => {
let eTargetOpt = e.target.closest("option");
if (!eTargetOpt) return;
if (!boxA.contains(eTargetOpt)) return;
if (eTargetOpt) {
boxB.appendChild(eTargetOpt);
boxB.selectedIndex = "-1";
boxA.removeChild(eTargetOpt);
};
e.stopPropagation();
}, false);
// When option in Box B is double-clicked, move it to Box A
boxB.addEventListener("dblclick", e => {
let eTargetOpt = e.target.closest("option");
if (!eTargetOpt) return;
if (!boxB.contains(eTargetOpt)) return;
if (eTargetOpt) {
boxA.appendChild(eTargetOpt);
boxA.selectedIndex = "-1";
boxB.removeChild(eTargetOpt);
};
e.stopPropagation();
}, false);
dualListBox("ctst1", "ctst2", dataFrame.selCollTubeSampTypes);
由于您基本上对两个选择使用相同的逻辑,因此我将其合并为一个函数。而不是使用ID,这可能是有问题的,我们可以使用一个单一的className,并依靠基本的JS来确定哪个是哪个。排序机制(您最初的问题)的工作原理是将所有选项元素放入数组中,按数据集对数组进行排序。索引,然后重新填充选择元素。一组逻辑适用于两个盒子
const dataFrame = {
"selCollTubeSampTypes": [
["CPT", "CPT"],
["SST", "SST"],
["EDTA", "EDTA"],
["PAXgene", "PAXgene"],
["NP SWB", "NP SWB"],
["OP SWB", "OP SWB"],
["RCTL SWB", "RCTL SWB"],
["Self NS", "Self NS"]
]
};
const dualListBox = (className, dataset) => {
let boxSet = document.querySelectorAll(`.${className}`);
dataset.forEach((item, i) => {
let val = item[0] != "" ? item[0] : item[1];
boxSet[0].innerHTML += `<option value="${val}" data-index="${i}">${item[1]}</option>`;
})
boxSet.forEach(myBox => myBox.addEventListener("dblclick", e => {
let eTargetOpt = e.target.closest("option");
if (!eTargetOpt) return;
let targBox = myBox == boxSet[0] ? boxSet[1] : boxSet[0]
if (eTargetOpt) {
let targOptions = [...targBox.querySelectorAll('option')];
targBox.innerHTML = '';
myBox.removeChild(eTargetOpt);
targOptions.push(eTargetOpt);
targOptions.sort((a, b) => a.dataset.index - b.dataset.index)
targOptions.forEach(opt => targBox.appendChild(opt))
}
e.stopPropagation();
}, false));
}
dualListBox("box-set", dataFrame.selCollTubeSampTypes);
<select class="form-control form-control-sm box-set" size="8" multiple></select>
<select class="form-control form-control-sm box-set" size="8" multiple></select>