Выбранный: сохранить порядок множественного выбора
Я использую Выбранный множественный выбор. Я хочу иметь возможность отслеживать выбранный пользователем заказ. Например, если пользователь сначала выбирает option2, а затем option1, я хочу получить результат в порядке option2 и option1. Но выбранные сортирует пользователя выбранные параметры. Есть ли способ, которым я могу сказать выбранное, чтобы не сортировать результат?
6 ответов
Я написал простой плагин для использования вместе с Chosen. Он позволяет вам получить порядок выбора элемента множественного выбора Chosen, а также установить его из массива упорядоченных значений.
Это доступно на Github: https://github.com/tristanjahier/chosen-order
Он совместим с Chosen 1.0+, а также с версиями jQuery и Prototype. Существует также плагин для каждого фреймворка, который позволяет вам делать такие вещи:
Получить порядок выбора
var selection = $('#my-list').getSelectionOrder();
Установить выбранные значения в порядке
var order = ['nioup', 'plop', 'fianle']; // Ordered options values
$('#my-list').setSelectionOrder(order);
Проверьте это.
Я предлагаю вам использовать Select2, если еще не слишком поздно. Он выглядит так же, как Chosen, но имеет гораздо лучшие API и документы.
С select2 это будет что-то вроде [непроверенный код]
var results = [];
$("#e11").on("change", function(e) {
results.push(e.val)
})
Теперь доступен плагин https://github.com/mrhenry/jquery-chosen-sortable/, который выполняет работу для выбранного v1.
Для более новых версий selected вам нужно заменить chzn на selected в файле github JS.
Чтобы использовать это я использую следующий код:
jQuery('#myselect').addClass('chosen-sortable').chosenSortable();
Это работает очень хорошо, но вам понадобится еще немного кода при повторном редактировании поля, чтобы изменить порядок элементов после загрузки выбранных.
Я использую следующее для этого. Имеется список sortedElements и $select = jQuery('#myselect'):
var $container = $select.siblings('.chosen-container')
var $list = $container.find('.chosen-choices');
// Reverse the list, as we want to prepend our elements.
var sortedElements = sortedElements.reverse();
for (var i = 0; i < sortedElements.length; i++) {
var value = sortedElements[i];
// Find the index of the element.
var index = $select.find('option[value="' + value + '"]').index();
// Sort the item first.
$list
.find('a.search-choice-close[data-option-array-index="' + index + '"]')
.parent()
.remove()
.prependTo($list);
}
Это работает очень хорошо здесь.
Вы можете добавлять / удалять элементы самостоятельно при изменении события.
// Your collection Array
var collectionArray = []
// make change event on chosen select field
chosenSelect.change(function () {
// first get the chosen results which might be in wrong order
var currentValues = $(this).val();
// get your current collection that is in the right order
var pastValues = collectionArray;
// see if you need to add or drop
if (currentValues.length > pastValue.length) {
// loop to get just the new item
pastValues.forEach(function(pastValue) {
currentValue = $.grep(currentValue, function(newItemOnly) {
return newItemOnly != pastValue;
});
});
// add your newItemOnly
collectionArray.push(currentValue[0]);
} else {
// here loop to get only the dropped value
currentValues.forEach(function(currentValue) {
pastValues = $.grep(pastValues, function(droppedValueOnly) {
return droppedValueOnly != currentValue;
});
});
// drop the value dropped from your collection
collectionArray = $.grep(collectionArray, function(updatedArray) {
return updatedArray != pastValues[0];
});
}
});
Я ввел обычай .change()
обработчик событий, чтобы заставить его работать:
$('.chosen-select').chosen({});
чтобы:
$('.chosen-select').chosen({}).change((event, info) => {
if (info.selected) {
var allSelected = this.querySelectorAll('option[selected]');
var lastSelected = allSelected[allSelected.length - 1];
var selected = this.querySelector(`option[value="${info.selected}"]`);
selected.setAttribute('selected', '');
lastSelected.insertAdjacentElement('afterEnd', selected);
} else { // info.deselected
var removed = this.querySelector(`option[value="${info.deselected}"]`);
removed.setAttribute('selected', false); // this step is required for Edge
removed.removeAttribute('selected');
}
$(this).trigger("chosen:updated");
});
Обратите внимание, что это перемещает DOM в случае выбора и не перемещается в случае отмены выбора. setAttribute
/removeAttribute
чтобы добиться видимых изменений в <option>
DOM.
Надеюсь, что это поможет кому-то еще искать способ сделать это, не делая ничего дополнительного при отправке.
PS: компактная jQuery-версия этого кода может быть написана при необходимости.:)
Надеюсь, что это полезно для людей, которые используют более старую версию select2 (меньше, чем v4). В этом случае полезны опции select2-selection и select2-Removal. Используя массив и добавляя значения после выбора, мы можем поддерживать порядок выбора и, отменив выбор конкретного параметра, можем найти индекс и удалить его из массива с помощью splice().
var selected = [];
$('#multiSelect').on("select2-selecting", function(evt) {
var selectedOption = evt.val;
selected.push(selectedOption);
}).on("select2-removing", function(evt) {
index = selected.indexOf(evt.val);
selected.splice(index,1);
});
Для версии 4 и выше можно использовать select2:select и select2:unselect.:)
Это будет организовано в порядке вашего выбора
$("select").on('select2:select', function (e) {
var elm = e.params.data.element;
$elm = jQuery(elm);
$t = jQuery(this);
$t.append($elm);
$t.trigger('change.select2');
});