Выберите все опции в 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
. Кто-нибудь знает об этом?
Ответы
Ответ 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 <a style="cursor:pointer;" id="allcheck">All</a>
| <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;
}
}