Comments 71
Сделано аккуратненько, молодцы!
Про баг
А откуда там вообще double-click взялся?
Дело там не в дабл клике, хотя он, наверное, может помочь. Нужно выбирать обычным кликом)
Смог воспроизвести баг. Но как он к программистам/не-программистам относится я не понял.
Это эмпирический вывод
Суть бага в том, чтобы сделать клик менее чем за 100 мс. Получается, что у людей с богатым опытом использования компьютера (профессиональным, игровым) скорость выше. У людей старшего поколения и тех кто с компьютером на Вы ничего не выходит.
Неточное описание поведения
Сначала у меня получалось не всегда.
Потом я нашёл надёжный способ выбрать любой пункт —
1.открыть дропдаун
2. не торопясь посмотреть на варианты
3. тут надо успеть за 100мс: нажать/зажать ctrl или shift или alt и сразу кликнуть мышкой

также работает если зажать кнопку заранее, потом отпустить и быстро кликнуть, но намного менее надёжно
У меня и моих коллег получалось в 100% случаев обычным щелчком. Специально хотели воспроизвести баг, но не могли. Только потом, когда понял в чем суть, удалось воспроизвести)
Долго не мог понять в чём дело, но всё же баг воспроизвёл. Посему вопрос: как можно было так криво сделать?
Это появилось из-за хака для всех браузеров кроме Хрома. В этих браузерах нельзя понять чем было вызвано событие blur, переводом фокуса или программно, поэтому пришлось проверять через некоторый промежуток времени что инпут действительно потерял фокус и триггерить blur на элементе селекта. Причем из-за особенностей браузерной работы с событиями этот промежуток времени не маленький. С 10 мс не работало, с 50 мс через раз. github.com/tamtakoe/oi.select/blob/0.2.8/src/services.js#L99
Без него в FF, IE и проч. не будет работать переход по табу. Т.е. фокус сместится с одного инпута на другой, но компонент об этом никак не узнает, т. к. нет элемента в event.relativeTarget и он подумает, что blur был вызван программно и не станет вызывать его второй раз.
А я, кажется, второй баг нашел — на странице «Funny» выбор с клавиатуры (нажатием Enter) не работает вообще никак.
Решил что я, наверное, совсем плохой программист )))
На странице Customization не скроллится список тачем, если при открытом списке тапнуть на строку. Win 10 + Firefox 41
Пара багов:
1) 938 пикселей по ширине экран www.dropbox.com/s/qupszykt884axpb/Screenshot%202015-08-30%2013.24.55.png?dl=0
2) Не открывается вверх, если места снизу нет www.dropbox.com/s/k8vbs275eirphyt/Screenshot%202015-08-30%2013.25.31.png?dl=0
3) Если открыть выпадашку стрелками, то автокамплит не работает, нельзя ввести значение, можно только выбрать. Хотя, это может быть и фича такая.

Пара замечаний:
1) На мобильных устройствах желательно оставлять оригинальный селект.
2) Если у контейнера, в котором лежит селект будет overflow:hidden, то могут быть неприятные баги. Например, обрезанная выпадашка.
3) Еще не нашел оригинального селекта на странице. Он удаляется?
Баги:
1) поправлю
2) Стандартный селект не поднимается наверх
image
Но идея хорошая, нужно будет сделать с помощью CSS.
3) не удалось повторить. Это в каком примере наблюдается?

Замечания:
1) В мобильных устройствах так же нет автокомплита, поэтому стандартный селект не прокатит.
2) Не знаю как это побороть и надо ли. Тут, наверное, будет лучше сделать вариант с выпадашкой наверх.
3) Стандартного селекта там нет. С ним получалось слишком костыльно.
2) Открывается наверх, попробуйте сделайте селект в самом низу страницы, без открытых дев-тулзов. Он откроется вверх.
3) В любом. Просто делаете фокус на селект и нажимаете стрелку вниз. Селект откроется, а написать ничего нельзя.

Про замечания:
1) Видимо стоит только для этого случая оставить кастомный. В остальных случаях 100% удобнее пользоваться нативным.
2) Стоит, неизвестно, в каком месте селект будет вызываться. Побороть легко, просто держите выпадашку в самом низу body и подцепляйте ее при открытии к селекту.
3) А в чем были костыли?
3) Странно. У меня можно писать и в Хроме и в ФФ. Что за система/браузер?

Подумаю, чтобы аппендить выпадашку к body или сделать такую опцию как в angular-bootstap для тултипов

Пробовал способ, когда в основе лежит стандартный селект, скрытый из виду, и в него копируются опции из oi-select. Нужно было перекомпилировать элемент, следить чтобы связь между областями видимости не порвалась при использовании, например, ng-if на директиве. Код был сложнее для восприятия, да и смысла не было, т. к. всё равно почти вся функциональность не была привязана к стандартному селекту.
Во-первых, он на jQuery, который уже как пол года назад удалось выпилить из проекта. Из jQuery нужна была только функция определения высоты элемента (меньше 100 строчек). Тащить ради нее всю библиотеку как-то странно.
Во-вторых, никакой совместимости по АПИ там и близко нет. Пришлось бы писать огромный адаптер или мучиться.
В-третьих, слишком много отсебятины. Для множественного выбора поле ввода находится в строке с выбранными элементами, для одиночного — в списке, чтобы удалить тег нужно попасть по маленькому крестику, какие-то крестики для одиночного ввода… Не продуманный дизайн. Такое ощущение, что его писали разные люди, которые не смогли договориться.
Практически то же самое. Год назад он был самым вменяемым, но, по сути, представлял обертку над select2, тащил jQuery и был глючным. Сейчас плагины подросли, но до уровня oi.select все еще не дотягивают. Пока ни один плагин не учитывает, что у Ангуляра есть готовое АПИ для селекта и предлагает свое, а это показатель уровня разработчиков.

P. S. Понравился в свое время brianreavis.github.io/selectize.js, с него скопировал лучшие наработки в дизайне.
По-моему, слишком много отсебятины. Какие-то крестики для очистки модели в одиночном инпуте. Для одиночного и множественного селекта поля поиска выглядят по-разному, список не закрывается по щелчку на пустом поле ввода (родной селект так себя не ведет). И как-то всё неаккуратно.
очистка в одиночном удобно, если есть несколько зависимых списков.

например,

страна — город — улица

тогда при очистке страны очищается и страна, и все зависимые.

одним кликом
Показываю крестик в варианте cleanModel: true (http://tamtakoe.github.io/oi.select/#/select/#cleanmodel)

Там модель очищается при клике в любом месте. Не сторонник маленьких кнопочек и крестиков, по которым фиг попадешь, особенно на мобильном устройстве)
какой-то странный баг — добавляет только ОДНО, первое значение. а дальше — ничего…

и только если редактируешь и опять добавляешь, тогда начинает добавлять и дальше.
delete button на самом деле нет. Ее добавляет фильтр по-умолчанию

.filter('oiSelectCloseIcon', ['$sce', function($sce) {
    return function(label) {
        var closeIcon = '<span class="close select-search-list-item_selection-remove">×</span>';

        return $sce.trustAsHtml(label + closeIcon);
    };
}])

В selectFilter можно переопределить на свой фильтр и делать там что угодно
Почему, когда фокус убирается с поля ввода, элемент добавляется? Возможно ли сделать так, чтобы добавлялся только по enter?
Вообще, не должен. Разве что в случае с одиночным селектом. Он показывает выбранное ранее значение. Это сделано специально, т. к. так ведет себя обычный селект
Баг — если редактируешь значение, то если в это время удалить другой элемент, то пропадают оба элемента.
Сейчас если стоит режим редактирования элементов, то удалить элемент как-бы нельзя. Т. е. из модели он удаляется, но на его месте остается его текст. Если вводить какой либо текст и удалить при этом любой элемент, то вводимый ранее текст заменится на текст удаленного элемента. Должно так работать
template.html очень не рекомендуется заменять на свой, т. к. это может нарушить работу элемента. Постарался сделать так, чтобы внешний вид можно было полностью настроить фильтрами и стилями.
и ещё

newItemModel: {id: null, name: $query},

как-бы id автоинкремент сделать?

update: понял, использовать newItemFn

Неплохой мультиселект. Некоторые примеры ведут себя не очевидным образом. У меня на первых порах тоже такое было. А вот валидацию текстового ввода возьму на заметку.
Спасибо за классную реализацию сохранения новой модели (http://tamtakoe.github.io/oi.select/#/select/#prompt).
Давно пытался найти такой плагин.

Сейчас очень серьезно размышляю о переходе с angular-ui/ui-select на ваше решение в своем большом проекте.

Подскажите, можно ли сделать вывод списка вот в таком формате:


Скриншот из демки ui-select

Нужно, чтобы в выпадающем меню выводилось несколько разных параметров, согласно моему шаблону, и чтобы работал фильтр (поиск) по всем параметрам (или, как это можно в ui-select, по тем, которые нужны).
Я нашел только такой пример — http://tamtakoe.github.io/oi.select/#/select/#customization, но там фильтр не работает совсем.
Для форматирования выбранных тегов нужно использовать searchFilter, для вариантов в списке — dropdownFilter. Поиск осуществляется только по одному полю, указанному в oi-options (что полностью соответствуют ng-options), но можно самому формировать поисковую выдачу:
— задать в качестве списка функцию, принимающую поисковую строку и возвращающую список tamtakoe.github.io/oi.select/#/select/#lazyloading
— переопределить listFilter в который передается поисковая строка и список в которой так же можно как угодно этот список фильтровать tamtakoe.github.io/oi.select/#/select/#customization

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

P. S. Как минимум в одном большом проекте это решение уже используется — в моём, так что если какие-то серьезные баги всплывают, узнаю об этом очень быстро)
А как сделать так, чтобы oi-options первоначально принял массив, а уже потооом был бы autocomplete?
функция, возвращающая список вариантов по строке должна возвращать все варианты, если строка пустая… Если правильно понял что было нужно
Никак нельзя (конечно, можно обернуть все в свою директиву или найти элемент селекта в контроллере, а там найти инпут и повеситься на Enter, но это нехорошо).

Нужно следить за изменением модели с помощью watch и выполнять нужные действия. Так код будет максимально независим от элемента селекта.
Вы могли бы добавить в код возможность подписки на событие keyDown в поле ввода?

В будущем перенесу нативные события инпута на елемент компонента
И ещё есть баг — если в пустое поле ввода сделать фокус, то вызывается функция autocomplete с пустым запросом. Думаю, нужно сделать так, чтобы не вызывалась.
Так специально сделано. При пустом запросе часто возвращают либо весь список либо популярные значения
К сожалению, пришлось отказаться от вашего плагина по причине отсутствия API событий и возможности расширения.
Сделал на коленке за часик свой редактор тагов.
События это зло. Их просто использовать, но невозможно отлаживать и они сильно ломают логику приложения. Лучше избегать их по возможности. Над расширением подумаю
Спасибо вам за плагин. Постепенно осваиваем как прозрачную замену чёрному ящику из костылей select2.

Пока возник вопрос с динамическими интерполяциями.

В нашем случае на форме при смене типа автомобиля меняется источник данных для списка трансмиссий, и одновременно обязательность этого поля. Если поле становится необязательным, пользователь должен уметь его очистить. В директиве есть опция cleanModel, но она проверяется один раз при компиляции, так что oi-select-options="{cleanModel:isRequired(vehicleType)}" выполнится только для исходного состояния формы. Смена vehicleType не приведёт к вычислению нового значения cleanModel и не разрешит очищать поле.

Есть ли возможность реализовать разбор elementOptions динамически и навесить этот разбор на нужные $watch (в нашем случае, смена источника данных)? Перекомпилировать всю директиву ради этого выглядит большим оверхедом.

Спасибо!
Посмотрю что можно сделать. Не обещаю, но постараюсь до нового года
Only those users with full accounts are able to leave comments. Log in, please.