Подтвердить что ты не робот

Выберите все опции в optgroup

У меня есть элемент select сгруппированным option s. Мне нужно выбрать (или отменить выбор) все option в optgroup при нажатии option. Я также должен иметь возможность одновременного выбора нескольких optgroup.

Я хочу, чтобы он работал:

  • Если ничего не выбрано, я хочу щелкнуть один параметр и получить все параметры в той же выбранной группе optgroup.
  • Если одна или несколько optgroups уже выбраны, я хочу нажать одну опцию в другой optgroup и выбрать все эти опции.
  • Если одна или несколько optgroups уже выбраны, я хочу иметь возможность Ctrl-щелкнуть опцию в не выбранной группе opt и выбрать все опции в этой группе optgroup.
  • Если одна или несколько optgroups уже выбраны, я хочу иметь возможность Ctrl-щелкнуть опцию в выбранной группе opt и убрать все опции в этой группе.

Глядя на другие ответы на 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 не может обрабатывать событие click на optgroup или option, поэтому я привязываю его к select, а затем использую $(ev.target). Но в IE8 $(ev.target) все еще указывает на весь select, а не на option, который был нажат. Как узнать, какой option (или содержащий optgroup), который был нажат, и был ли он выбран или отменен?

Другим неожиданным поведением, но незначительным в сравнении, является то, что в Chrome (20.0) снятие выделения происходит не до тех пор, пока мышь не покинет select. Кто-нибудь знает об этом?

4b9b3361

Ответ 1

не ответ на конкретный вопрос о проблемах с выбором обозревателя, я думаю, что на это уже был дан ответ, но решение проблемы выбора данных и передачи их обратно на сервер будет заключаться в изменении вашей маркировки на что-то который лучше подходит для многократного выбора

если вы используете флажки вместо этого, вы можете поместить их в список и добавить усиление 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/ добавляет родительский флажок, чтобы сделать его более удобным)

Ответ 2

Так как Internet Explorer с версии 10 по-прежнему не поддерживает никаких полезных событий в optgroup или 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 (путем нажатия и перетаскивания вниз, как показано на снимке экрана):

multiple options selected spanning multiple optgroups

Разрешение конфликтов по умолчанию для этого случая - всегда использовать последний optgroup, но его можно изменить, чтобы всегда использовать первый, или optgroup с наибольшим количеством уже выбранных параметров.

Ответ 3

это исправить проблему, вам нужно только добавить этот код после выбора 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

Ответ 4

    <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");
            });
        }
    });
});

Ответ 5

В соответствии с вашей проблемой выберите/отмените выбор всех параметров. вы можете попробовать следующий код, может вам помочь.

код:

Код 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>

Ответ 6

Надеюсь, что это сработает

$("#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;
}
}