Контрол для ввода тэгов на JavaScript

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

Причем сделать еще одну фичу в нем, которой мне очень не хватало в старом добром select2 - это возможность проверять тэги на ходу.
Т.е. например человек не выбрал из списка, а просто написал тэг вручную и контрол конечно же будет считать его новым тэгом (т.к. выбран не из списка), а хотелось бы такую штуку, чтобы после ввода тэга контрол сходил и посмотрел - есть ли такой тэг и если он есть, снял с него метку "новый" + поправил название, если пользователь набрал не основное название тэга.

Ой сложно то как... в общем, в демке все будет ясно (попробуйте набрать например rd и ввод).

Контрол основан на том моем автокомплитере, чтобы не плодить ненужных сущностей. Т.е. для работы ему требуются файлы автокомплитера (css + js) и плагин jquery.autGrowInput.js, подсмотренный мной на stackoverflow и чуть допиленный. Ну и для некоторых браузеров может понадобиться json2.js.

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


Демо

Ввод тэгов, использующий массив


API


Создание

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

dataURL для загрузки данных либо массив данных
optionsдополнительный настройки:
delimitersстрока, содержащая все символы, возможные в качестве разделителя тэгов (по умолчанию , и [enter])
allowNewTagstrue - если можно добавлять новые тэги, а не только выбирать их из списка (по умолчанию false)
inputClassимя класса поля ввода тэгов (по умолчанию tagsinput)
DDClassимя класса для блока результата, если нужно
DDzIndexz-index блока результата (по умолчанию 10000)
DDminCharsкол-во символов, после которых идет поиск (по умолчанию 1)
DDdelayвремя ожидания в миллисекундах после нажатия клавиши и до попытки поиска (по умолчанию 400)
DDmaxItemsToShowмаксимальное кол-во результатов в списке (если -1 - без ограничений, по умолчанию -1)
DDhighlightFirsttrue - при появлении результатов, первый из них автоматически подсвечивается (по умолчанию false)
DDwidthширина выпадающего списка (0 - рассчитывается автоматически = ширине поля ввода, по умолчанию 0)
DDheightмаксимальная высота выпадающего списка, если элементов больше - появляется прокрутка (0 - неограничена, по умолчанию 0)
loadingClassимя класса поля ввода при ожидании результатов с сервера, если нужно
cacheLengthмаксимальное число кэшируемых результатов поиска (если 0 - кэширование будет отключено, -1 - бесконечно, по умолчанию 10)
mustMatchtrue и поле не выбрано - после потери фокуса оно очистится (по умолчанию false)
extraParamsдополнительные параметры при запросе на сервер (объект имя:значение)
delayвремя в миллисекундах, после добавления тэга и до вызова фии проверки тэгов (по умолчанию 400)
msgNotFoundсообщение, показываемое, если ничего не найдено (по умолчанию not found...)
msgServerErrorсообщение, показываемое при ошибке сервера (по умолчанию server error...)
msgErrorсообщение, показываемое при других ошибках (по умолчанию error...)
checkTagstrue - включения встроенной функции проверки тэгов, false - отключение данной функции, или пользовательская функция, по умолчанию false
parseDataфункция преобразования входных данных
DDformatItemфункция формирования вида элемента списка
formatItemфункция формирования вида элемента тэга
eventsHandlerфункция обработки событий


Формат данных
Данные, пересылаемые как JSON, или объявленные и переданные как массив должны быть в минимально необходимом виде такими:
[
	{
 		id:		id элемента1,
 		text:		"название элемента1",
		pattern:	[ "синосним1", "синоним2", ... ],
		_ti_:		{
			"new":	false,
			check:	false
		}
 	},
 	{
 		id:		id элемента2,
 		text:		"название элемента2",
		pattern:	[ "синоним1", "синоним2", ... ]
 	},
 	...
]
Если у элемента присутствуют дополнительные поля, кроме минимально необходимых - они сохранятся в нем и их можно будет потом использовать.
Необязательный элемент _ti_ говорит о том, как отображать данный тэг.
Если new = true - тэг будет отображаться как "новый", если check = true - тэг будет проверен при разрешенной операции проверки тэгов.
Если не указать id тэг будет автоматически считаться новым и будет проверен при операции проверки тэгов.

Запрос на поиск идет вида POST со строкой в переменной q, и переменной mode = search, кроме того в переменной items находятся все текущие выбранные тэги в JSON.
Элементы, содержащиеся в items при запросе будут в том-же формате, который показан выше. Если у тэга не указан id, то он будет равным null, у всех тэгов будет сформирован элемент _ti_.


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



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

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

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


Функция формирования вида тэга
function formatItem( container, tag ) {
	...
	return HTML / DOM объект / null данного тэга;
}
containerDOM объект в котором будет храниться тэг и его данные
tagданные тэга

Должна возвращать HTML или DOM данного элемента (или null, если не нужно)


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

Значения event:

DDover / DDoutнаведение / снятие наведения с элемента в списке (obj - DOM элемента, item - данные элемента)
DDselectвыбор элемента в списке (obj - DOM элемента, item - данные элемента)
DDunselectотмена выбора элемента (obj - null, item - данные элемента)
DDshow / DDhideпоказывание / скрытие списка (obj - DOM списка)
DDbeforeRequestвызывается до того, как пойдет запрос на поиск (obj - options, item - options.extraParams)
checkStartстандартная процедура проверки тэгов начинает проверку (obj - пришедшие данные из запроса в виде объекта)
checkEndстандартная процедура проверки тэгов закончила проверку (obj - пришедшие данные из запроса в виде объекта)
checkErrorстандартная процедура проверки тэгов получила на запрос ответ с ошибкой (obj - пришедшие данные из запроса в виде объекта или текста)
deletedтэг удален (obj - DOM удаленного тэга)
duplicateпри создании тэга выявлено, что это дубль уже существующего элемента, создание отменено (obj - DOM найденного оригинального элемента, item - данные элемента-дубля, еще 2 доп. переменных: newTag и checkTag - признаки для элемента-дубля )
insertдобавление тэга (obj - DOM тэга, item - данные тэга)
addдобавлен тэг из списка (obj - DOM тэга)
addNewсоздан новый тэг (obj - DOM тэга)


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

ti.get( onlyData, idOnly );
onlyDatatrue - вернет массив, состоящих только из данных выбранных тэгов / false - вернет массив DOM элементов выбранных тэгов
idOnlytrue - вернет массив из id выбранных тэгов (если у тэга нет - он не попадет в этот массив), работает только при onlyData = true

Если ни одного тэга не выбрано вернет пустой массив.


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

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

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

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


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

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


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

ti.setExtraParams(
	{
		parameter1: value,
		parameter2: value,
		parameter3: value,
		...
	}
);

Устанавливает параметры, идущие при ajax-запросе, переписывает options.extraParams, если был задан.


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

ti.showResults( status, timer );
statustrue - показать / false - спрятать
timertrue - показать список со стандартной задержкой


Методы: проверить и убрать дубликаты

ti.removeDupes();
Проверить на дубликаты выбранные тэги, и убрать их, если найдены.


Методы: проверить тэги

ti.checkTags();
Запустить проверку тэгов.


Описание логики работы проверки тэгов

Если в checkTags указана своя функция, то она должна быть вида
function( checkedItems, itemsForCheck ) {}
checkedItemsсписок DOM объектов уже проверенных тэгов
itemsForCheckсписок DOM объектов тэгов для проверки

В DOM элементе, в аттрибуте data-item хранятся данные тэга ({ id: ..., text: ..., pattern: ..., ... }).

Признаки check и new - это соответственные классы данного DOM элемента.
checkedItems + itemsForCheck - это все тэги, которые на данный момент выбраны.

До название тэга добраться можно так (например для первого элемента): itemsForCheck[0].firstChild.textContent (textNode).

Если в checkTags указано true - т.е. включена встроенная функция проверки тэгов, то проверка тэгов будет работать только через ajax.

Перед ajax запросом каждому тэгу будет сгенерировано уникальное ID, которое сохраняется в его DOM, в атрибут data-id.

Затем будет запущен ajax запрос на url с параметрами mode=check, items c данными всех выбранных тэгов (в формате JSON).

В каждое "данное" тэга ставится дополнительный член _ti_:
[
	{
		id:	id тэга (отсутствует у нового тэга или null)
		text:	текст тэга,
		pattern: ...
		...
		_ti_: {
			id:		сгенерированное ID для данного тэга,
			"new":	true | false,
			check:	true | false,
		}
	},
	...
]

Обратно будет ожидаться JSON массив с элементами, которые требуются модифицировать:
[
	{
		id:	id тэга (отсуствует у нового тэга или null)
		text:	текст тэга,
		....
		_ti_: {
			id:		ID из запроса, который пришел
			"new":	true | false,
			check:	true | false,
			del:	true | false
		}
	},
	...
]

Если есть _ti_.id и _ti_.del = true, то тэг будет удален (в этом случае можно передавать в _ti_ только id и del)

Если есть _ti_.id, то тэг с данным id будет модифицирован - все его данные будут заменены пришедшими данными, это же будет с его new / check.

Если нет _ti_.id, то данный тэг будет создан и добавлен в конец выбранных тэгов.


Данные тэга в его DOM

В DOM элементе, в атрибуте data-item хранятся все данные этого тэга ({ id: ..., text: ..., pattern: ..., ... }).

Признаки check и new - это соответственные классы данного DOM элемента, если они = false, то они просто отсутствуют.


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

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

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


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

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

16.11.14
  • первый публичный релиз
скачать

16.11.2014, Protocoder
Написать комментарий