选择optgroup中的所有选项

时间:2012-10-24 10:15:15

标签: javascript jquery html

我有一个select元素,其中包含option个分组。单击option时,我需要选择(或取消选中)optgroup中的所有option。我还需要能够同时选择多个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无法处理clickoptgroup上的option事件,这就是我将其绑定到select然后使用的原因$(ev.target)。但在IE8中,$(ev.target)仍然指向整个select,而不是指向被点击的option。如何找出被点击的option(或包含optgroup)以及是否已选中或取消选择?

另一个意外的行为,但相比较小,是在Chrome(20.0)中,取消选择直到鼠标离开select才会发生。有人知道解决方法吗?

6 个答案:

答案 0 :(得分:3)

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

如果您使用复选框,则可以将它们放在列表中并添加enhanching js以选择all并取消选择所有

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/添加一个父复选框以使其更有用)

答案 1 :(得分:1)

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

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

我在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(通过点击并向下拖动,如屏幕截图所示):

multiple options selected spanning multiple optgroups

此情况的默认冲突解决方案是始终使用最后一个optgroup,但可以更改为始终使用第一个,或optgroup已选择最多的选项。< / p>

答案 2 :(得分: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' } )

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

答案 3 :(得分: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");
            });
        }
    });
});

答案 4 :(得分:-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>

答案 5 :(得分:-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;
}
}