Автокомплитер на JavaScript

Опять встала проблема найти что-то легковесное и удобное, на это раз нужен был автокомплитер (подсказчик).

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

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

А если у меня города, и я хочу чтобы при вводе слова Питер или Петербург, ну или Petersburg всплывал Saint Petersburg? Нее, не слышал!
А на самом деле это очень распространенная задача, когда за несколькими различными словами скрывается какое-то одно значение.

Опять придется самому делать.
Хотя как всегда - инет большой - может плохо смотрел.

Поскольку я, как и любой программист, ленив - часть CSS и суть работы некоторых блоков взял из мода довольно распространенного автокомплитера отсюда.

Требования к автокомплитеру

  • возможность быстрого "прикрепления" на поле ввода
  • возможность иметь несколько синонимов одного значения
  • возможность сохранять произвольные поля для элемента и обращаться к ним
  • возможность работы как с локальным массивом, так и с подгружаемыми данными

Что получилось

Демо

автокомплитер, использующий массив

автокомплитер, использующий подгрузку
и обработку событий (подсказка)


API


Создание

var ac = $ ( селектор текстового поля ).autocompleter( data, options );

dataURL для загрузки данных либо массив данных
optionsдополнительный настройки:
methodPOST / GET (по умолчанию POST)
paramNameназвание переменной, куда пишется строка запроса (по умолчанию q)
dataTypeформат ожидаемых данных (по умолчанию json)
inputClassимя класса для поля ввода
resultsClassимя класса для блока результата
loadingClassимя класса при ожидании результатов с сервера
selectedClassимя класса когда поле с выбранным элементом
minCharsкол-во символов, после которых идет поиск (по умолчанию 1)
delayвремя ожидания в миллисекундах после нажатия клавиши и до попытки поиска (по умолчанию 400)
cacheLengthмаксимальное число кэшируемых результатов поиска (если 0 - кэширование будет отключено, -1 - бесконечно, по умолчанию 10)
maxItemsToShowмаксимальное кол-во результатов в списке (если -1 - без ограничений, по умолчанию -1)
mustMatchесли true, и элемент не выбран, после потери фокуса оно очистится
extraParamsобъект, - дополнительные параметры при запросе на сервер
widthширина выпадающего списка (если 0 - рассчитывается автоматически = ширине поля ввода, по умолчанию 0)
heightмаксимальная высота выпадающего списка, если элементов больше - пояыляется прокрутка (если 0 - неограниченна, по умолчанию 0)
highlightFirstесли true при появлении результатов, первый из них автоматически подсвечивается (по умолчанию false)
msgNotFoundсообщение, показываемое, если ничего не найдено (по умолчанию not found...)
msgServerErrorсообщение, показываемое при ошибке сервера (по умолчанию server error...)
msgErrorсообщение, показываемое при других ошибках (по умолчанию error...)
parseDataфункция преобразования входных данных
formatItemфункция формирования вида элемента списка
eventsHandlerфункция обработки событий


Формат данных
Данные, пересылаемые как JSON, или объявленные и переданные как массив должны быть в минимально необходимом виде такими:
[
	{
		text:		"название элемента1",
		pattern:	[ "синоним1", "синоним2" ... ]
	},
	{
		text:		"название элемента2",
		pattern:	[ "синоним1", "синоним2" ... ]
	},
	{
		text:		"название элемента3",
		pattern:	[ "синоним1", "синоним2" ... ]
	}
]
Если у элемента присутствуют дополнительные поля, кроме минимально необходимых - они сохранятся в нем и их можно будет потом использовать.

Запрос на данные идет вида POST со строкой в переменной q.


Функция преобразования входных данных
function parseData( items ) { ... return items; }
itemsвходные данные



Функция формирования вида элемента списка
function formatItem( container, item, itemNumber, items, itemsLen ) {
	...
	return {
		html:	(null или строка или DOM объект), - html / DOM объект данного элемента списка,
		value:	строка, - значение, помещаемое при выборе в поле ввода
	};
}
containerDOM объект в котором будет храниться элемент и его данные
itemданные элемента
itemNumberпорядковый номер элемента в списке
itemsданные всех элементов
itemsLenколичество всех элементов

Должна возвращать объект с полями:

htmlHTML данного элемента (или null, если не нужно)
titleзначение title для данного элемента (или null, если не нужно)
valueзначение, помещающееся в поле ввода при выборе данного элемента


Функция обработки событий
function eventsHandler( event, obj, item, query ) { ... }
Значения event:

over / outнаведение / снятие наведения с элемента в списке (obj - DOM элемента, item - данные элемента)
selectвыбор элемента в списке (obj - DOM элемента, item - данные элемента)
unselectотмена выбора элемента (obj - null, item - данные элемента)
show / hideпоказывание / скрытие списка (obj - DOM списка)
beforeRequestвызывается до того, как пойдет запрос на поиск (obj - options, item - options.extraParams, query - строка запроса)
в extraParams будет присутствовать свойство с именем, заданным paramName со значением, равным строке запроса
данные в extraParams будут неизменным между запросами (кроме параметра с именем из paramName), если не менялись специально
если при обработке этого события функция что-либо вернет, то данное значение будет использовано вместо extraParams


Методы: получить значение

ac.get();
Возвращает объект с двумя членами value - это то, что написано внутри контрола, и selected - это то, что было выбрано из списка (может быть null, если ничего не выбирали)

Выбранный элемент можно получить, обратившись к атрибуту data-selected текстового поля, на которое был установлен автокомплитер.


Методы: установить значение

ac.set( value, item, triggerEvent );
valueтекст внутри контрола
itemобъект устанавливаемого элемента
triggerEventtrue - для генерации событий изменения (может быть опущен, по умолчанию false)

Если опущены все параметры, контрол просто очищается.

Под "опущено" подразумевается значение undefined или null.


Методы: очистить кэш

ac.clearCache();
Очистка кэша результатов.


Методы: установить параметры запроса

ac.setExtraParams(
	{
		parameter1: value,
		parameter2: value,
		parameter3: value,
		...
	}
);
Устанавливает параметры, идущие при ajax-запросе, переписывает options.extraParams, если был задан.


Методы: показать список

ac.showResults( status, timer );
Показать / спрятать выпадающий список результатов.

statustrue - показать / false - спрятать
timertrue - показать список со стандартной задержкой



Данные выбранного элемента DOM

Данные выбранного элемента можно получить, обратившись к атрибуту data-selected текстового поля, на которое был установлен автокомплитер.

Данные элемента в списке хранятся в его DOM (li) аттрибуте data-item.


Как обращатся к методам?

Либо так:
var ac = $( селектор текстового поля ).autocompleter( ... )
ac.метод(...);

Либо так:
$( селектор текстового поля ).autocompleter().метод(...);

Скачать ac.zip, версия от 07.03.18

Все файлы автокомплитера одним архивом.
История версий:

07.03.18
  • пофикшены мелкие баги
  • добавлена работа с minChars=0
  • добавлены новые параметры method, paramName, dataType
  • изменено событие beforeRequest (старое поведение сохранено)
  • в процедуре обработки событий добавился четвертый параметр query для события beforeRequest
  • обновлена документация
23.11.14
  • переработана документация
03.11.14
  • переработка кода, улучшение стабильности
  • добавлен метод showResults
  • ВНИМАНИЕ! событие prepare заменено на beforeRequest
18.06.14
  • добавлена поддержка события onInput
04.04.14
  • первый публичный релиз
скачать

04.04.2014, Protocoder
ua6lvy13.04.2014 15:40:23#ответить
Питербург пишется через "е" :), а правильно в базе иметь правильное название города - Санкт-Петербург.
Protocoder13.04.2014 17:32:36#ответить
Ну, сути проблемы это не меняет - город не найдется, если нет синонимов его названия, как бы он ни назывался в БД :) А за поправку спасибо.
Написать комментарий