【问题标题】:How can I make an HTML multiple select act like the control button is held down always如何使 HTML 多选像控制按钮始终被按住一样
【发布时间】:2012-09-17 03:25:09
【问题描述】:

我正在开发一个 Web 应用程序,它需要一个 HTML 多选元素,其操作方式就像始终按住控制键一样。 IE。点击一个选项将切换它是否被选中。

我尝试了各种 Jquery 事件绑定,但似乎标准的 HTML 多选行为在 Jquery 绑定事件触发之前执行,因此几乎不可能简单地拦截事件并修改标准行为。

我怎样才能让单击来切换单个选项的选择?

【问题讨论】:

标签: javascript jquery html select


【解决方案1】:

您可能需要考虑一个更简单的解决方案,例如在其溢出属性设置为滚动的 div 中使用复选框列表。这可能对你更好。得到一个下拉菜单来做你所要求的有点复杂。

例如看这个:

label{display:block;}
    #container{height:100px;width:200px;overflow:scroll;}
<div id="container">
        <label><input type="checkbox" name="test" value="1" />Option 1</label>
        <label><input type="checkbox" name="test" value="2" />Option 2</label>
        <label><input type="checkbox" name="test" value="3" />Option 3</label>
        <label><input type="checkbox" name="test" value="4" />Option 4</label>
        <label><input type="checkbox" name="test" value="5" />Option 5</label>
        <label><input type="checkbox" name="test" value="6" />Option 6</label>
        <label><input type="checkbox" name="test" value="7" />Option 7</label>
        <label><input type="checkbox" name="test" value="8" />Option 8</label>
        <label><input type="checkbox" name="test" value="9" />Option 9</label>
        <label><input type="checkbox" name="test" value="10" />Option 10</label>
        <label><input type="checkbox" name="test" value="11" />Option 11</label>
        <label><input type="checkbox" name="test" value="12" />Option 12</label>
    </div>

【讨论】:

    【解决方案2】:

    试试这个。您可以将选项值存储在对象中,并使用单击操作更新对象,然后将更改应用于选择。

    演示

    http://jsfiddle.net/iambriansreed/BSdxE/

    HTML

    <select class="select-toggle" multiple="multiple">
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
    </select>​
    

    JavaScript

    $('.select-toggle').each(function(){    
        var select = $(this), values = {};    
        $('option',select).each(function(i, option){
            values[option.value] = option.selected;        
        }).click(function(event){        
            values[this.value] = !values[this.value];
            $('option',select).each(function(i, option){            
                option.selected = values[option.value];        
            });    
        });
    });​
    

    【讨论】:

    • 我在下面的回答中对这个想法做了一个更完善的版本,它还支持 shift-clicks 和拖动选择。
    • aaaaand 示例 #1001 在 IE 中没有做任何该死的事情。
    • 这里有一个更好的解决方案:stackoverflow.com/questions/2096259/…
    【解决方案3】:

    必须自己解决这个问题,并注意到bugged behavior a simple interception of the mousedown 和设置属性会有,所以覆盖了 select 元素并且效果很好。

    jsFiddle: http://jsfiddle.net/51p7ocLw/

    注意:此代码确实通过替换 DOM 中的选择元素来修复错误行为。这有点激进,会破坏您可能附加到元素的事件处理程序。

    window.onmousedown = function (e) {
        var el = e.target;
        if (el.tagName.toLowerCase() == 'option' && el.parentNode.hasAttribute('multiple')) {
            e.preventDefault();
    
            // toggle selection
            if (el.hasAttribute('selected')) el.removeAttribute('selected');
            else el.setAttribute('selected', '');
    
            // hack to correct buggy behavior
            var select = el.parentNode.cloneNode(true);
            el.parentNode.parentNode.replaceChild(select, el.parentNode);
        }
    }
    <h4>From</h4>
    
    <div>
        <select name="sites-list" size="7" multiple>
            <option value="site-1">SITE</option>
            <option value="site-2" selected>SITE</option>
            <option value="site-3">SITE</option>
            <option value="site-4">SITE</option>
            <option value="site-5">SITE</option>
            <option value="site-6" selected>SITE</option>
            <option value="site-7">SITE</option>
            <option value="site-8">SITE</option>
            <option value="site-9">SITE</option>
        </select>
    </div>

    【讨论】:

    • 这是一个不错的解决方案。我尝试了更多,但它有点奇怪,点击后,列表会滚动回顶部。在有很多选项的长选择中,这真的很奇怪。
    【解决方案4】:

    上述解决方案都具有不支持复选框中的选择的主要缺点,这实际上是我首先使用&lt;select&gt;-boxes 而不是复选框输入的原因。最初我访问此页面是为了找到解决此问题的内置方法,但考虑到上述答案,我将只编写自己的代码。

    以下代码还有一个优点,即它不会在 mouseup 上更新,而不是在 iambriansreed 当前的最佳答案上更新,而是在 mousedown 上更新,这是浏览器中的默认行为。

    只是为了帮助未来的谷歌员工,我的代码如下:

    // Copyright (c) 2018 Joeytje50. All rights reserved.
    // This code is licenced under GNU GPL3+; see <http://www.gnu.org/licenses/>
    
    // Source code and most recent version:
    // https://gist.github.com/Joeytje50/2b73f9ac47010e7fdc5589788b80af77
    
    // select all <options> within `sel` in the range [from,to]
    // change their state to the state sel.options[from] is in,
    // ie. change it to the current state of the first selected element
    function selectRange(sel, from, to) {
      var toState = sel.options[from].selected;
      // make sure from < to:
      if (from > to) {
        var temp = from;
        from = to;
        to = temp;
      }
      if (!(sel instanceof HTMLSelectElement)) {
        throw new TypeError('selectRange requires a single non-jQuery select-element as first parameter');
      }
      // (de)select every element
      for (var i=from; i<=to; i++) {
        sel.options[i].selected = toState;
      }
    }
    
    $(function() {
      $('.addSelect').data('select-start', 0); // default selection start
      $('.addSelect').on('mousedown', function(e) {
        $(this).focus();
        // clicking on the edge of the <select> shouldn't do anything special
        if (!$(e.target).is('option')) return;
        // if Ctrl is pressed, just let the built-in functionality take over
        if (e.ctrlKey) return;
        // keep everything selected that's not affected by the range within a shift-click
        if (e.shiftKey) {
          var fromIdx = $(this).data('select-start')
          selectRange(this, $(this).data('select-start'), e.target.index);
          e.preventDefault();
          return false;
        }
        // save the starting <option> and the state to change to
        $(this).data('select-start', e.target.index);
        e.target.selected = !e.target.selected;
        e.preventDefault();
        // save a list of selected elements, to make sure only the selected <options>
        // are added or removed when dragging
        var selected = [];
        for (var i=0;i<this.selectedOptions.length;i++) {
          selected.push(this.selectedOptions[i].index);
        }
        $(this).data('selected', selected);
        $(this).children('option').on('mouseenter', function(e) {
          var sel = this.parentElement;
          // first reset all options to the original state
          for (var i=0;i<sel.options.length;i++) {
            if ($(sel).data('selected').indexOf(i) == -1) {
              sel.options[i].selected = false;
            } else {
              sel.options[i].selected = true;
            }
          }
          // then apply the new range to the elements
          selectRange(sel, $(sel).data('select-start'), e.target.index);
        });
      });
      // clean up events after click event has ended.
      $(window).on('mouseup', function() {
        $('.addSelect').children('option').off('mouseenter'); // remove mouseenter-events
      });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <select class="addSelect" multiple size="10">
    <option value="0">Foo0</option>
    <option value="1">Bar1</option>
    <option value="2">Baz2</option>
    <option value="3">Lol3</option>
    <option value="4">Heh4</option>
    <option value="5">Hey5</option>
    <option value="6">Meh6</option>
    <option value="7">Xcq7</option>
    <option value="8">Hmm8</option>
    <option value="9">End9</option>
    </select>

    只需将该代码复制到您想在其上使用的任何项目,即可随意使用。

    【讨论】:

      猜你喜欢
      • 2021-02-03
      • 1970-01-01
      • 2014-07-02
      • 2017-06-11
      • 1970-01-01
      • 2015-04-21
      • 2016-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多