12

我有一个select带有分组的元素option。单击 an时,我需要选择(或取消选择)所有options 。我还需要能够一次选择多个 s。optgroupoptionoptgroup

我希望它的工作方式是这样的:

  • 如果未选择任何内容,我想单击一个选项并选择同一 optgroup 中的所有选项。
  • 如果已经选择了一个或多个 optgroup,我想单击另一个 optgroup 中的一个选项,然后选择所有这些选项。
  • 如果已经选择了一个或多个 optgroup,我希望能够按住 Ctrl 键单击未选择的 optgroup 中的选项,并选择该 optgroup 中的所有选项。
  • 如果已经选择了一个或多个 optgroup,我希望能够按住 Ctrl 键单击所选 optgroup 中的一个选项,并取消选择该组中的所有选项。

查看 Stack Overflow 上的其他答案,我创建了以下内容:

HTML:

<select multiple="multiple" size="10">
    <optgroup label="Queen">
        <option value="Mercury">Freddie</option>
        <option value="May">Brian</option>
        <option value="Taylor">Roger</option>
        <option value="Deacon">John</option>
    </optgroup>
    <optgroup label="Pink Floyd">
        <option value="Waters">Roger</option>
        <option value="Gilmour">David</option>    
        <option value="Mason">Nick</option>                
        <option value="Wright">Richard</option>
    </optgroup>
</select>

jQuery:

$('select').click(selectSiblings);
function selectSiblings(ev) {
    var clickedOption = $(ev.target);
    var siblings = clickedOption.siblings();
    if (clickedOption.is(":selected")) {
        siblings.attr("selected", "selected");
    } else {
        siblings.removeAttr("selected");
    }
}​

我在这里做了一个例子:http: //jsfiddle.net/mflodin/Ndkct/ (遗憾的是jsFiddle似乎不再支持IE8了。)

这在 Firefox (16.0) 中按预期工作,但在 IE8 中它根本不起作用。从其他答案中,我发现 IE8 无法处理orclick上的事件,这就是我将其绑定到然后使用. 但在 IE8 中,仍然指向整个而不是被点击的那个。如何找出单击了哪个(或包含)以及它是被选中还是取消选中?optgroupoptionselect$(ev.target)$(ev.target)selectoptionoptionoptgroup

另一个意想不到的行为,但相比之下较小,是在 Chrome (20.0) 中,直到鼠标离开select. 有人知道解决方法吗?​</p>

4

6 回答 6

3

不是选择选项跨浏览器问题的具体问题的答案,我认为已经回答了,但是选择数据并将其传递回服务器的问题的解决方案是将您的标记更改为更适合的东西多选

如果您改用复选框,则可以将它们放在列表中并添加增强js以全选和取消全选

http://jsfiddle.net/Ndkct/43/

<dl>
<dt>Queen</dt>
<dd>
    <ul>
        <li>
            <input id="Mercury" name="bandmembers" value="Mercury" type="checkbox" />
            <label for="Mercury">Freddie</label>
        </li>    
        <li>
            <input id="May" name="bandmembers" value="May" type="checkbox" />
            <label for="May">Brian</label>
        </li>    
        <li>
            <input id="Taylor" name="bandmembers" value="Taylor" type="checkbox" />
            <label for="Taylor">Roger</label>
        </li>    
        <li>
            <input id="Deacon" name="bandmembers" value="Deacon" type="checkbox" />
            <label for="Deacon">John</label>
        </li>    
    </ul>
</dd>
<dt>Pink Floyd</dt> ...

js 现在已经足够简单了

$("dt")
    .css("cursor","pointer")
    .click(function(){
        var $el = $(this).next();
        var $checks = $el.find(":checkbox");
        if($checks.is(":not(:checked)")){
           $checks.attr("checked",true); 
        }else{
           $checks.attr("checked",false); 
        }
    });

(这个小提琴http://jsfiddle.net/Ndkct/44/添加了一个父复选框以使其更有用)

于 2013-04-19T09:10:38.727 回答
2

由于 Internet Explorer 版本 10 仍然不支持optgroupor上的任何有用事件option,因此针对此问题的任何跨浏览器解决方案都不能依赖于来自这些元素的直接事件。

注意: MSDN 文档声称optgroup支持click事件,但从 IE 10 开始,这似乎仍然不是现实: http: //msdn.microsoft.com/en-us/library/ie/ms535876(v=vs.85) .aspx

我在 Chrome 27、Firefox 20、Safari 6、IE 9 和 IE 10 中测试了以下内容(我目前无法访问 IE 8)。

这是您可以使用的示例:http: //jsfiddle.net/potatosalad/Ndkct/38/

// Detect toggle key (toggle selection)
$('select')
    .on('mousedown', function(event) {
        // toggleKey = Command for Mac OS X; Control for others
        var toggleKey = (!event.metaKey && event.ctrlKey && !(/Mac OS/.test(navigator.userAgent))) ? event.ctrlKey : event.metaKey;
        if (toggleKey === true) {
            $(this).data('toggleKey', true);
        }
        $(this).data('_mousedown', true);
    })
    .on('mouseup', function() {
        $(this).data('_mousedown', null);
    });
// Chrome fix for mouseup outside select
$(document).on('mouseup', ':not(select)', function() {
    var $select = $('select');
    if ($select.data('_mousedown') === true) {
        $select.data('_mousedown', null);
        $select.trigger('change');
    }
});

$('select')
    .on('focus',  storeState)
    .on('change', changeState);

function storeState() {
    $(this).data('previousGroup', $('option:selected', this).closest('optgroup'));
    $(this).data('previousVal',   $(this).val());
};

function changeState() {
    var select = this,
        args   = Array.prototype.slice.call(arguments);

    var previousGroup = $(select).data('previousGroup'),
        previousVal   = $(select).data('previousVal');
    var currentGroup  = null,
        currentVal    = $(select).val();

    var selected = $('option:selected', select),
        groups   = selected.closest('optgroup');

    console.log("[change] %o -> %o", previousVal, currentVal);

    if ((previousVal === currentVal) && (groups && groups.length == 1)) {
        // selected options have not changed
        // AND
        // only 1 optgroup is selected
        // -> do nothing
    } else if (currentVal === null || currentVal.length === 0) {
        // zero options selected
        // -> store state and do nothing
        storeState.apply(select, args);
    } else { // a select/deselect change has occurred
        if ($(select).data('toggleKey') === true
            && (previousVal !== null && previousGroup !== null && groups !== null)
            && (previousVal.length > currentVal.length)
            && (previousGroup.length === groups.length)
            && (previousGroup.get(0) === groups.get(0))) {
            // options within the same optgroup have been deselected
            // -> deselect all and store state
            $(select).val(null);
            storeState.apply(select, args);
        } else if (currentVal.length === 1) {
            // single option selected
            // -> use groups
            currentGroup = groups;
        } else if (groups.length === 1) {
            // multiple options selected within same optgroup
            // -> use groups
            currentGroup = groups;
        } else {
            // multiple options selected spanning multiple optgroups
            // -> use last optgroup
            currentGroup = groups.last();
        }
    }

    $(select).data('toggleKey', null);

    if (currentGroup !== null) {
        $('optgroup', select).not(currentGroup).children(':selected').attr('selected', false);
        $(currentGroup).children(':not(:selected)').attr('selected', true);
        storeState.apply(select, args);
    }
};

它通过将先前选择的组和选项存储在select元素上并确定optgroup应该选择(或取消选择)哪些来工作。

可以根据开发人员的需要更改某些行为。例如,在选择多个options跨越多个的情况下optgroups(通过单击并向下拖动,如屏幕截图所示):

跨越多个 optgroup 选择了多个选项

这种情况下的默认冲突解决方案是始终使用最后一个optgroup,但可以更改为始终使用第一个,或者optgroup具有最大数量的已选择选项。

于 2013-04-15T19:27:03.907 回答
0

这解决了问题,您只需要在选择 init 后添加此代码。

$( '.chzn-results .group-result' ).each( function () {
    var self      = $( this )
        , options = $( '~li', self )
        , next    = options.filter( '.group-result' ).get( 0 )
    ;
    self.data( 'chzn-options', options.slice( 0, options.index( next ) ) );
} )
.click( function () { 
    $( this ).data( 'chzn-options' ).mouseup()
 } )
.hover( function () { 
    $( this ).data( 'chzn-options' ).addClass( 'highlighted' );
 }, function () { 
    $( this ).data( 'chzn-options' ).removeClass( 'highlighted' );
 } )
.css( { cursor: 'pointer' } )

感谢在 github 上发布此修复程序的 adriengibrat:
https ://github.com/harvesthq/chosen/issues/323

于 2013-02-27T18:31:50.787 回答
0
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


$(document).ready(function() {
    $('select').click(function(tar) {
        var justClickValue = tar.target.value;

        var selectedGroup = $('option[value="'+justClickValue+'"]').parent();

        if (selectedGroup.hasClass("allSelected")) {
            selectedGroup.removeClass("allSelected");
            $("option").each(function() {
                $(this).removeAttr("selected");
            });
        } else {
            $(".allSelected").removeClass("allSelected");
            selectedGroup.addClass("allSelected");
            $(".allSelected option").each(function() {
                $(this).attr("selected", "selected");
            });
        }
    });
});
于 2013-04-18T08:02:19.877 回答
-1

希望这会奏效

$("#SelectID").live("click",function() {
var elements = this.options; //or document.getElementById("SelectID").options;
for(var i = 0; i < elements.length; i++){
   if(!elements[i].selected)
    elements[i].selected = true;
}
}
于 2013-02-27T10:52:22.850 回答
-1

根据您的问题选择/取消选择所有选项。您可以尝试以下代码,可能会对您有所帮助。

代码:

javascript代码:

 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js">

       $(function(){

                $('#allcheck').click(function(){
                var chk=$('#select_option >optgroup > option');
                chk.each(function(){
                  $(this).attr('selected','selected');
            });
   });  
$('#alluncheck').click(function(){

              var chk=$('#select_option >optgroup > option');
              chk.each(function(){
              $(this).removeAttr('selected');
          });
     });});

html代码:

       <select multiple="multiple" size="10" id="select_option" name="option_value[]">
          <optgroup label="Queen">
            <option value="Mercury">Freddie</option>
            <option value="May">Brian</option>
            <option value="Taylor">Roger</option>
            <option value="Deacon">John</option>
        </optgroup>
        <optgroup label="Pink Floyd">
            <option value="Waters">Roger</option>
            <option value="Gilmour">David</option>    
            <option value="Mason">Nick</option>                
            <option value="Wright">Richard</option>
       </optgroup>
 </select>
<br>
       <strong>Select&nbsp;&nbsp;<a style="cursor:pointer;" id="allcheck">All</a>
  &nbsp;|&nbsp;<a style="cursor:pointer;"  id="alluncheck">None</a></strong>
于 2013-02-27T09:28:11.843 回答