it-roy-ru.com

Как избежать необходимости ctrl-щелчка в окне с несколькими вариантами выбора, используя Javascript?

Я думал, что это будет простой взлом, но теперь я искал часы и не видел, чтобы найти правильный поисковый запрос. Я хочу иметь обычное поле множественного выбора (<select multiple="multiple">), за исключением того, что я не хочу, чтобы пользователь держал нажатой клавишу управления, чтобы сделать множественный выбор. 

Другими словами, я хочу, чтобы левый щелчок переключал элемент <option>, находящийся под курсором, без изменения каких-либо других. Другими словами, я хочу что-то, что выглядит как поле со списком, но ведет себя как группа флажков.

Кто-нибудь может предложить простой способ сделать это в Javascript? Благодарю.

54
bokov

Проверьте эту скрипку: http://jsfiddle.net/xQqbR/1022/

В основном вам нужно переопределить событие mousedown для каждого <option> и переключить там свойство selected.

$('option').mousedown(function(e) {
    e.preventDefault();
    $(this).prop('selected', !$(this).prop('selected'));
    return false;
});

Для простоты я дал «option» в качестве селектора выше. Вы можете настроить его так, чтобы он соответствовал <option>s под определенные элементы <select>. Например: $('#mymultiselect option')

90
techfoobar

Пришлось решить эту проблему самому и заметил, что в поведении ошибка простого перехвата mousedown и установки атрибута, поэтому сделал переопределение элемента select, и он работает хорошо.

jsFiddle: http://jsfiddle.net/51p7ocLw/

Примечание: Этот код исправляет некорректное поведение, заменяя элемент select в DOM. Это немного агрессивно и сломает обработчики событий, которые вы могли прикрепить к элементу.

window.onmousedown = function (e) {
    var el = e.target;
    if (el.tagName.toLowerCase() == 'option' && el.parentNode.hasAttribute('multiple')) {
        e.preventDefault();

        // toggle selection
        if (el.hasAttribute('selected')) el.removeAttribute('selected');
        else el.setAttribute('selected', '');

        // hack to correct buggy behavior
        var select = el.parentNode.cloneNode(true);
        el.parentNode.parentNode.replaceChild(select, el.parentNode);
    }
}
<h4>From</h4>

<div>
    <select name="sites-list" size="7" multiple>
        <option value="site-1">SITE</option>
        <option value="site-2" selected>SITE</option>
        <option value="site-3">SITE</option>
        <option value="site-4">SITE</option>
        <option value="site-5">SITE</option>
        <option value="site-6" selected>SITE</option>
        <option value="site-7">SITE</option>
        <option value="site-8">SITE</option>
        <option value="site-9">SITE</option>
    </select>
</div>

18
Sergio

ответ techfoobar ошибочен, он отменяет выбор всех параметров, если вы перетаскиваете мышь.

Ответ Серхио интересен, но клонирование и удаление событий, связанных с выпадающим списком, не очень хорошая вещь.

Попробуйте этот ответ .

Примечание: не работает в Firefox, но отлично работает в Safari/Chrome/Opera. (Я не проверял это на IE)

5
evilReiko

Necromancing. 
Выбранный ответ без jQuery. 
Кроме того, он пропустил настройку фокуса при нажатии на опцию, потому что вы должны сделать это самостоятельно, если напишите e.preventDefault ... 
Если вы забудете сделать фокус, это повлияет на CSS-стилизацию, например начальная загрузка и т. д.

var options = [].slice.call(document.querySelectorAll("option"));

options.forEach(function (element)
{
    // console.log("element", element);
    element.addEventListener("mousedown", 
        function (e)
        {
            e.preventDefault();
            element.parentElement.focus();
            this.selected = !this.selected;
            return false;
        }
        , false
    );
});
0
Stefan Steiger

У меня была та же самая проблема сегодня, обычно совет состоит в том, чтобы использовать список скрытых флажков и эмулировать поведение с помощью css, таким способом легче управлять, но в моем случае я не хочу изменять html.

На данный момент я тестировал этот код только с Google Chrome, я не знаю, работает ли с другим браузером, но он должен:

var changed;
$('select[multiple="multiple"]').change(function(e) {
    var select = $(this);
    var list = select.data('prevstate');
    var val = select.val();
    if (list == null) {
        list = val;
    } else if (val.length == 1) {
        val = val.pop();
        var pos = list.indexOf(val);
        if (pos == -1)
            list.Push(val);
        else
            list.splice(pos, 1);
    } else {
        list = val;
    }
    select.val(list);
    select.data('prevstate', list);
    changed = true;
}).find('option').click(function() {
    if (!changed){
        $(this).parent().change();
    }
    changed = false;
});

Конечно, предложения приветствуются, но я не нашел другого пути

0
Marino Di Clemente