使用 jQuery Select2 隐藏搜索选项

Hide Options On Search with jQuery Select2

我正在使用 Select2 插件,但我这辈子都弄不明白。

基本上我所做的是允许用户从颜色列表和选项 "Other" 中选择 5 种颜色。因此,显示了 10 种左右的颜色,并在底部显示了选择 "Other" 的选项。这些 "Other" 选项在选择时绑定了一个颜色选择器,因此用户可以选择其他颜色。

现在,我允许他们这样做的唯一方法是创建 5 个选项,所有选项的名称都为 "Other",这样用户可以根据需要选择其他 5 次。我的问题是当用户开始在搜索框中键入查询时,我无法正确隐藏不是第一个显示的 "Other" 选项。

我这样做是在打开正常结果的情况下

$('.multi-select').select2('misc options').on("select2:open", function () {
    $('.select2-results__option[aria-selected="false"]:contains("Other"):not(:eq(0))').hide();
    $('.select2-results__option[aria-selected="false"]:contains("Other"):eq(0)').show();
});

但是,当我像这样将相同的函数绑定到搜索输入元素的变化时

$('.select2-search__field').on('keyup', function () {
    $('.select2-results__option[aria-selected="false"]:contains("Other"):not(:eq(0))').css({
           'display': 'none',
           'opacity': 0
     });
     $('.select2-results__option[aria-selected="false"]:contains("Other"):eq(0)').css({
           'display': 'block',
           'opacity': 1
     });
});

如果 Select2 决定将结果显示在上面是合适的,我得到了元素的疯狂闪烁,除了顶部 "Other" 选项漂浮在 select 对象上方非常高的地方window space 限制。

闪烁可以归因于插件将显示事件绑定到对象的'keydown'(和'keypress'),所以我绑定到同一个触发器被覆盖,让我绑定到 'keyup',这会导致框显示在按键和释放之间。

我不会修改插件来执行此操作,但是我无法弄清楚我需要在插件内部编辑什么才能使其正常工作。


杂项。我尝试过的事情包括设置 css selector 总是使每个包含 "Other" 的 Select2 对象的第一个框,但是没有 css selector类似“:包含”的东西。

将 class 应用于 Select2 创建的 <li></li> 以指定它是否是 "Other" 选项,但这由插件控制,所以我没有控制权以上。

我明白了。由于字段的值被用作后端字段的 ID,我可以在 ID 上附加“-other-color”,所以我有办法 select 在 CSS 允许超越闪烁。

.select2-results__options li[id*="-other-color"][aria-selected="false"] ~ li[id*="-other-color"][aria-selected="false"]{
    display:none!important;
}

由于列表中的子项多于其他颜色选项,您需要根据属性使用波浪号 selector 到 select selector 之后的所有内容正在 selected。

我建议结合使用 select2:select 事件和 maximumSelectionLength 选项,而不是修改 "Other" 结果来实现您正在寻找的结果。

因此,您将从包含默认颜色列表和 一个 "Other" 选项的标记开始。

<select multiple="multiple">
  <option value="red">Red</option>
  <option value="blue">Blue</option>
  <option value="green">Green</option>
  <option value="yellow">Yellow</option>
  <option value="custom">Other</option>
</select>

注意,我把"Other"选项的value设置为custom,你可以随便选,只要不和颜色冲突就行。这只是将用于确定何时显示颜色选择器的 "flag" 选项。

为了最终将 select 离子的数量限制为仅五种颜色,您可以将 maximumSelectionLength 选项设置为 5 来初始化 Select2。这将告诉 Select2 只允许五个 select 离子,你可以找到一个例子 in the documentation.

var $element = $("select").select2({
  maximumSelectionSize: 5
});

现在您已经限制了 select 离子的数量,我们可以继续通过 "Other" 选项实现颜色选择器。我们可以通过侦听 select2:select 选项来检测 "Other" 选项何时被 selected,只要选项被 selected.

就会触发。
$element.on("select2:select", function (evt) {
  // handle the "Other" option
});

从那里你需要专门检测 "Other" 选项,所以我们可以检查通过 select2:select 事件传入的数据对象是否有 id of [=21] =],这是我们之前设置的。由于您希望 selecting 多个自定义颜色选项保持打开状态,我们将在 selected 时立即取消 select "Other" 选项。

function (evt) {
  // check for the custom id
  if (evt.params.data.id === 'custom') {
    // unselect the element, so other custom colors can be picked
    evt.params.data.element.selected = false;

    // update the selection
    $(this).trigger('change');
  }
}

从那里开始,您需要实现用户可以选择颜色的部分。为此,我只使用了 prompt 来询问颜色。因为 prompt 是同步的,所以我们可以等待 selection 被给出。但是您的颜色选择器很可能是异步的,因此您可能必须将其余部分放在不同的事件处理程序中。

// prompt the user for a color somehow
var color = prompt("Pick a color, any color");

颜色 select 编辑后,您将需要为其创建自定义 <option selected>。这是为了将值发送到服务器,这样 Select2 就可以知道 selected.

是什么颜色
// create a new option
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement/Option
var option = new Option(color, color, null, true);

您需要做的就是将它添加到原始 <select> 并触发其上的 change 事件,这样 Select2(和其他组件)就会知道该值已更改。

// add the option to the original select, before the "Other" option
$(option).insertBefore(evt.params.data.element);

// update the selection
$element.trigger('change');

现在 Select2 将显示新的自定义颜色以及已制作的任何其他 select离子。用户还可以通过多次 selecting "Other" 选项来 select 其他颜色。

因此,将它们放在一起可以得到以下代码

var $element = $("select").select2({
  maximumSelectionLength: 5
});

$element.on('select2:select', function (evt) {
  // check for the custom id
  if (evt.params.data.id === 'custom') {
    // unselect the element, so other custom colors can be picked
    evt.params.data.element.selected = false;

    // update the selection
    $(this).trigger('change');

    // prompt the user for a color somehow
    var color = prompt("Pick a color, any color");

    // create a new option
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement/Option
    var option = new Option(color, color, null, true);

    // add the option to the original select, before the "Other" option
    $(option).insertBefore(evt.params.data.element);

    // update the selection
    $element.trigger('change');
  }
});

您可以在以下 jsbin 进行实时测试:http://jsbin.com/beluximesi/1/edit?html,js,output