14

作業中のWebアプリケーションがあり、HTMLの複数選択要素が、Ctrlキーを常に押したままのように動作する必要があります。つまり、オプションをクリックすると、それが選択されているかどうかが切り替わります。

さまざまなJqueryイベントバインドを試しましたが、Jqueryバインドイベントが発生する前に標準のHTML複数選択動作が実行されるため、イベントをインターセプトして標準動作を変更することはほとんど不可能です。

シングルクリックで個々のオプションの選択を切り替えるにはどうすればよいですか?

4

4 に答える 4

17

これを試してみてください。オプション値をオブジェクトに保存し、クリックアクションを使用してオブジェクトを更新してから、選択に変更を適用できます。

デモ

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];        
        });    
    });
});​
于 2012-09-25T15:22:29.723 に答える
5

オーバーフロープロパティがスクロールに設定されている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>

于 2012-09-25T15:22:13.317 に答える
2

この問題を自分で解決する必要があり、バグのある動作に気づいたので、属性を単純にインターセプトしmousedownて設定すると、select要素がオーバーライドされ、正常に機能します。

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

注:このコードは、DOMのselect要素を置き換えることにより、バグのある動作を修正します。これは少し攻撃的であり、要素にアタッチした可能性のあるイベントハンドラーを壊します。

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>

于 2014-12-20T08:12:03.263 に答える
0

上記のソリューションはすべて、チェックボックスでの選択をサポートしないという大きな欠点があります。これが<select>、最初にチェックボックス入力ではなくボックスを使用する理由です。最初はこのページにアクセスして、これを修正するための組み込みの方法を見つけましたが、上記の回答を考慮して、独自のコードを作成します。

次のコードには、iambriansreedによる現在の上位の回答とは対照的に、mouseupでは更新されないという利点もありますが、ブラウザーのデフォルトの動作である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>

このコードを使用したいプロジェクトにコピーするだけで、このコードを自由に使用できます。

于 2018-01-12T00:04:23.647 に答える