使用 Vanilla JS 重新排序 select 选项列表

Reorder select option list using Vanilla JS

您好,我有一个选项下拉列表,其中包含按字母顺序排列的水果列表,其中一些缺货。我想要实现的是将下拉列表中的缺货选项移至列表底部,以便库存商品显示在缺货商品上方。

我的想法是找到其中包含缺货的任何选项,然后添加名为 outOfStock 的 class 并将其移至列表底部。为了尝试这样做,我使用其 innerHTML 为每个产品创建了一个数据值并搜索值“缺货”,但这似乎只有在我在查询中具有完整数据值时才有效。有没有一种方法可以找到所有“缺货”的数据值?或者是否有不同的解决方案建议我可以将缺货商品移至选项列表的底部?任何帮助将不胜感激

for (const element of document.querySelectorAll(".form-dropdown option")) {
  element.dataset.product = element.innerHTML;
}

document.querySelector(".form-dropdown option[data-product='Cherry - Out of stock']").classList.add('outOfStock');
<select class="form-dropdown">
<option disabled="" value="">Choose option</option>
<option value="0">Apple</option>
<option value="1">Banana</option>
<option value="2">Cherry - Out of stock</option>
<option value="3">Kiwi</option>
<option value="4">Lemon - Out of stock</option>
<option value="5">Melon - Out of stock</option>
<option value="6">Watermelon</option>
</select>

执行此操作的最佳方法是在将项目添加为 HTML 之前对其进行排序,但在这里我将它们从 HTML 中删除,然后排序并重新应用tp HTML.

for (const element of document.querySelectorAll(".form-dropdown option")) {
  element.dataset.product = element.innerHTML;
}

document.querySelector(".form-dropdown option[data-product='Cherry - Out of stock']").classList.add('outOfStock');

const select = document.querySelector('select');

const options = document.querySelectorAll('option');

const sortOptions = [];

      options.forEach(option => sortOptions.push(option));
      
      sortOptions.sort((a,b) => a.innerHTML.indexOf('- Out') > -1 ? -1 : 1);
      
      select.innerHTML = '';
     
      sortOptions.forEach(option => select.appendChild(option));
<select class="form-dropdown">
<option disabled="" value="">Choose option</option>
<option value="0">Apple</option>
<option value="1">Banana</option>
<option value="2">Cherry - Out of stock</option>
<option value="3">Kiwi</option>
<option value="4">Lemon - Out of stock</option>
<option value="5">Melon - Out of stock</option>
<option value="6">Watermelon</option>
</select>

我已经查看了一堆重复的答案,例如 ,但不太喜欢这些答案,所以我写了自己的答案。

最简单的方法是删除有问题的选项,然后重新附加它们。这会将它们按顺序移动到最后。

示例代码如下:

document.querySelectorAll('.form-dropdown').forEach(function(select) {
  Array.from(select.options).forEach(function(option) {
    if (option.innerText.includes("Out of stock")) {
      select.removeChild(option);
      select.appendChild(option);
      option.setAttribute("disabled", true);
    }
  });
});
<select class="form-dropdown">
  <option disabled="" value="">Choose option</option>
  <option value="0">Apple</option>
  <option value="1">Banana</option>
  <option value="2">Cherry - Out of stock</option>
  <option value="3">Kiwi</option>
  <option value="4">Lemon - Out of stock</option>
  <option value="5">Melon - Out of stock</option>
  <option value="6">Watermelon</option>
</select>

此处的其他答案显示了如何对现有元素进行排序。因此,当您征求建议时,我实际上建议不要硬编码 select 选项,而是创建一个对象数组并动态生成 selection。像这样:

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
    <select class="form-dropdown">
        <option disabled="" value="">Choose option</option>
    </select>
    <script>
        let products = [
            {name: "Apple", inStock: true},
            {name: "Banana", inStock: true},
            {name: "Cherry", inStock: false},
            {name: "Kiwi", inStock: true},
            {name: "Lemon", inStock: false},
            {name: "Melon", inStock: false},
            {name: "Watermelon", inStock: true}
        ]

        products.sort((a, b) => {
            if(a.inStock) {
                return -1
            }
        })

        var menu = (document.getElementsByClassName("form-dropdown"))[0]

        products.forEach(item => {
            var opt = document.createElement("option")
            opt.value = item.name

            if(item.inStock) opt.text = item.name
            else opt.text = item.name + " - Out of Stock"

            menu.add(opt)
        })
    </script>
</body>
</html>