Выбранный: сохранить порядок множественного выбора

Я использую Выбранный множественный выбор. Я хочу иметь возможность отслеживать выбранный пользователем заказ. Например, если пользователь сначала выбирает 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');
});
Другие вопросы по тегам