UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,518 lines 57.2 kB
Object.defineProperties(exports, {
	__esModule: { value: true },
	[Symbol.toStringTag]: { value: "Module" }
});
require("./kendo.html.button.js");
require("./kendo.list.js");
require("./kendo.mobile.scroller.js");
require("./kendo.virtuallist.js");
const require_prefix_suffix_containers = require("./prefix-suffix-containers-yJWbAuxw.js");
require("./kendo.html.chip.js");
require("./kendo.html.chiplist.js");
//#region ../src/kendo.multiselect.js
const __meta__ = {
	id: "multiselect",
	name: "MultiSelect",
	category: "web",
	description: "The MultiSelect widget allows the selection from pre-defined values.",
	depends: [
		"list",
		"html.chip",
		"html.chiplist",
		"html.button"
	],
	features: [{
		id: "mobile-scroller",
		name: "Mobile scroller",
		description: "Support for kinetic scrolling in mobile device",
		depends: ["mobile.scroller"]
	}, {
		id: "virtualization",
		name: "VirtualList",
		description: "Support for virtualization",
		depends: ["virtuallist"]
	}]
};
(function($, undefined) {
	var kendo = window.kendo, ui = kendo.ui, List = ui.List, encode = kendo.htmlEncode, html = kendo.html, keys = $.extend({ A: 65 }, kendo.keys), activeElement = kendo._activeElement, ObservableArray = kendo.data.ObservableArray, ID = "id", CHIP = ".k-chip", ACCEPT = "accept", FILTER = "filter", REBIND = "rebind", OPEN = "open", CLOSE = "close", CHANGE = "change", PROGRESS = "progress", SELECT = "select", DESELECT = "deselect", SELECTALL = "selectAllChange", ARIA_DISABLED = "aria-disabled", ARIA_READONLY = "aria-readonly", ARIA_EXPANDED = "aria-expanded", ARIA_HIDDEN = "aria-hidden", ARIA_ACTIVEDESCENDANT = "aria-activedescendant", FOCUSEDCLASS = "k-focus", SELECTEDCLASS = "k-selected", HOVERCLASS = "k-hover", STATEDISABLED = "k-disabled", NOCLICKCLASS = "k-no-click", DISABLED = "disabled", READONLY = "readonly", AUTOCOMPLETEVALUE = "off", ns = ".kendoMultiSelect", CLICK = "click" + ns, KEYDOWN = "keydown" + ns, MOUSEENTER = "mouseenter" + ns, MOUSELEAVE = "mouseleave" + ns, HOVEREVENTS = MOUSEENTER + " " + MOUSELEAVE, quotRegExp = /"/g, isArray = Array.isArray, styles = [
		"font-family",
		"font-size",
		"font-stretch",
		"font-style",
		"font-weight",
		"letter-spacing",
		"text-transform",
		"line-height"
	];
	var MultiSelect = List.extend({
		init: function(element, options) {
			var that = this, id, disabled;
			that.ns = ns;
			List.fn.init.call(that, element, options);
			if (that.options.summarizeAfter !== null && that.options.tagMode === "single") that.options.summarizeAfter = null;
			that._optionsMap = {};
			that._customOptions = {};
			that.options.inputMode = that.options.inputMode || that.element.attr("inputmode") || "text";
			if (!kendo.isPresent(that.options.readonly) && that.element.attr("readonly")) that.options.readonly = true;
			else if (!kendo.isPresent(that.options.readonly)) that.options.readonly = false;
			that._wrapper();
			that._inputValuesContainer();
			that._tagList();
			that._input();
			that._textContainer();
			that._clearButton();
			that._arrowButton();
			that._tabindex(that.input);
			element = that.element.attr("multiple", "multiple").hide();
			options = that.options;
			if (!options.placeholder) options.placeholder = element.data("placeholder");
			id = element.attr(ID);
			if (!id) id = kendo.guid();
			if (id) {
				that._tagID = id + "_tag_active";
				id = id + "_taglist";
				that.tagList.attr(ID, id);
			}
			that._initialOpen = true;
			if (options.label) this._label();
			that._aria();
			that._dataSource();
			that._ignoreCase();
			that._popup();
			that._tagTemplate();
			that.requireValueMapper(that.options);
			that._initList();
			that.listView.content.removeClass("k-list-scroller");
			that._aria();
			if (that.options.virtual) that.listView.one("listBound", function() {
				that._aria();
			});
			that.listView.bind("dataBound", function() {
				that._aria();
			});
			that._reset();
			that._enable();
			that._placeholder();
			if (options.autoBind) that.dataSource.fetch();
			else if (options.value) that._preselect(options.value);
			disabled = $(that.element).parents("fieldset").is(":disabled");
			if (disabled) that.enable(false);
			that._toggleCloseVisibility();
			that._applyCssClasses();
			require_prefix_suffix_containers.addInputPrefixSuffixContainers({
				widget: that,
				wrapper: that.wrapper,
				options: that.options,
				prefixInsertBefore: that._inputValuesContainer,
				suffixInsertAfter: options.clearButton ? that._clear : that.element.find("k-input-values")
			});
			if (that.floatingLabel) that.floatingLabel.refresh();
			kendo.notify(that);
			List.fn.endInit.call(that);
		},
		options: {
			name: "MultiSelect",
			tagMode: "multiple",
			enabled: true,
			autoBind: true,
			autoClose: true,
			readonly: null,
			highlightFirst: true,
			dataTextField: "",
			dataValueField: "",
			filter: "startswith",
			ignoreCase: true,
			minLength: 1,
			messages: {
				"singleTag": "item(s) selected",
				"clear": "clear",
				"deleteTag": "delete",
				"noData": "No data found.",
				"downArrow": "select",
				"selectAll": "Select all"
			},
			enforceMinLength: false,
			delay: 100,
			downArrow: false,
			value: null,
			maxSelectedItems: null,
			placeholder: "",
			height: 200,
			animation: {},
			virtual: false,
			itemTemplate: "",
			tagTemplate: "",
			groupTemplate: (data) => encode(data),
			fixedGroupTemplate: (data) => encode(data),
			prefixOptions: { separator: true },
			suffixOptions: { separator: true },
			clearButton: true,
			autoWidth: false,
			popup: null,
			size: undefined,
			fillMode: undefined,
			rounded: undefined,
			label: null,
			adaptiveTitle: null,
			adaptiveSubtitle: null,
			selectAll: false,
			checkboxes: false,
			summarizeAfter: 10
		},
		events: [
			OPEN,
			CLOSE,
			CHANGE,
			SELECT,
			DESELECT,
			SELECTALL,
			"filtering",
			"dataBinding",
			"dataBound",
			"kendoKeydown"
		],
		setDataSource: function(dataSource) {
			this.options.dataSource = dataSource;
			this._state = "";
			this._dataSource();
			this.persistTagList = false;
			this.listView.setDataSource(this.dataSource);
			if (this.options.autoBind) this.dataSource.fetch();
		},
		setOptions: function(options) {
			var listOptions = this._listOptions(options);
			List.fn.setOptions.call(this, options);
			this.listView.setOptions(listOptions);
			if (options.selectAll === false) this._removeSelectAllHeader();
			else if (options.selectAll === true && this.listView.bound()) {
				this._renderSelectAllHeader();
				this._updateSelectAllHeader();
			}
			this._accessors();
			this._aria();
			this._tagTemplate();
			this._placeholder();
			this._clearButton();
			this._arrowButton();
		},
		currentTag: function(candidate) {
			var that = this;
			if (candidate !== undefined) {
				if (that._currentTag) {
					that._currentTag.removeClass(FOCUSEDCLASS).removeAttr(ID);
					that._currentTag.find(".k-chip-action").attr(ARIA_HIDDEN, true);
					that.input.removeAttr(ARIA_ACTIVEDESCENDANT);
				}
				if (candidate) {
					candidate.addClass(FOCUSEDCLASS).attr(ID, that._tagID);
					candidate.find(".k-chip-action").removeAttr(ARIA_HIDDEN);
					that.input.attr(ARIA_ACTIVEDESCENDANT, that._tagID);
				}
				that._currentTag = candidate;
			} else return that._currentTag;
		},
		dataItems: function() {
			return this.listView.selectedDataItems();
		},
		destroy: function() {
			var that = this, ns = that.ns;
			clearTimeout(that._busy);
			clearTimeout(that._typingTimeout);
			if (that.filterInput) that.filterInput.off(ns);
			that.wrapper.off(ns);
			that.tagList.off(ns);
			that.input.off(ns);
			that._clear.off(ns);
			List.fn.destroy.call(that);
		},
		_onActionSheetCreate: function() {
			var that = this;
			that.filterInput.on("keydown" + ns, that, that._keydown.bind(that)).on("input" + ns, that._search.bind(that)).on("paste" + ns, that._search.bind(that)).attr({
				"role": "combobox",
				"aria-expanded": false,
				"aria-controls": that.input.attr("aria-controls"),
				"aria-autocomplete": that.input.attr("aria-autocomplete"),
				"aria-describedby": that.input.attr("aria-describedby"),
				"placeholder": that.options.placeholder
			});
			that.popup.bind("activate", () => {
				that.filterInput.val(that.input.val());
				that.filterInput.trigger("focus");
			});
			that.popup.bind("deactivate", () => {
				that.input.trigger("focus");
			});
		},
		_aria: function() {
			var that = this, ul = that.ul, id = ul.length ? ul[0].id : null, autocomplete = this.options.filter === "none" ? "none" : "list", tagListId = that.tagList.attr(ID);
			if (!id) return;
			that.input.attr({
				"role": "combobox",
				"aria-expanded": false,
				"aria-controls": id,
				"aria-autocomplete": autocomplete,
				"aria-describedby": tagListId
			});
			that._ariaLabel(that._focused);
		},
		_updateSelectedVirtualDataItemsIndexes: function() {
			const that = this;
			const listView = that.listView;
			const selectedIndexes = listView?._selectedIndexes;
			const selectedItems = listView?._selectedDataItems;
			const customOptions = that?._customOptions || {};
			const optionsMap = that._optionsMap || {};
			if (selectedIndexes && selectedItems) selectedIndexes.forEach((_, index) => {
				const field = that.options.dataValueField;
				const dataItem = selectedItems[index];
				const newIdx = optionsMap[dataItem[field]];
				customOptions[dataItem[field]] = newIdx !== undefined ? newIdx : customOptions[dataItem[field]];
			});
		},
		_activateItem: function() {
			if (this.popup.visible()) List.fn._activateItem.call(this);
			this.currentTag(null);
		},
		_listOptions: function(options) {
			var that = this;
			var listOptions = List.fn._listOptions.call(that, $.extend(options, {
				selectedItemChange: that._selectedItemChange.bind(that),
				selectable: "multiple"
			}));
			var itemTemplate = this.options.itemTemplate || this.options.template;
			var template = listOptions.itemTemplate || itemTemplate || listOptions.template;
			if (!template) template = (data) => encode(kendo.getter(listOptions.dataTextField)(data));
			listOptions.template = template;
			if (that.options.checkboxes) listOptions.checkboxes = true;
			return listOptions;
		},
		_setListValue: function() {
			List.fn._setListValue.call(this, this._initialValues.slice(0));
		},
		_listChange: function(e) {
			var data = this.dataSource.flatView();
			var optionsMap = this._optionsMap;
			var valueGetter = this._value;
			if (this._state === REBIND) this._state = "";
			for (var i = 0; i < e.added.length; i++) if (optionsMap[valueGetter(e.added[i].dataItem)] === undefined) {
				this._render(data);
				break;
			}
			this._selectValue(e.added, e.removed);
		},
		_selectedItemChange: function(e) {
			var items = e.items;
			var context;
			var idx;
			for (idx = 0; idx < items.length; idx++) {
				context = items[idx];
				this.tagList.children(CHIP).eq(context.index).children("span").first().html(this.tagTextTemplate(context.item));
			}
		},
		_wrapperMousedown: function(e) {
			var that = this;
			var notInput = e.target.nodeName.toLowerCase() !== "input";
			var target = $(e.target);
			var closeButton = target.closest(".k-input-button, .k-chip").children("[class*='-i-chevron-down']")[0];
			var removeButton = target.closest("[class*='-i-x']")[0];
			if (notInput && !(removeButton && kendo.support.mobileOS) && e.cancelable) e.preventDefault();
			if (!removeButton) if (closeButton && that.popup.visible()) that.toggle(false);
			else {
				if (that.input[0] !== activeElement() && notInput) that.input.trigger("focus");
				if (that.options.minLength === 1 && !that.popup.visible()) that.open();
			}
		},
		_inputFocus: function() {
			const that = this;
			that._placeholder();
			that.wrapper.addClass(FOCUSEDCLASS);
		},
		_inputFocusout: function(e) {
			var that = this;
			if (that.filterInput && e.relatedTarget === that.filterInput[0]) return;
			clearTimeout(that._typingTimeout);
			that.wrapper.removeClass(FOCUSEDCLASS);
			that.tagList.children(CHIP).removeClass(FOCUSEDCLASS);
			that._placeholder();
			that.close();
			if (that._state === FILTER) {
				that._state = ACCEPT;
				that.listView.skipUpdate(true);
			}
			if (that.listView.bound() && that.listView.isFiltered()) {
				that.persistTagList = true;
				that._clearFilter();
			}
			that.element.trigger("blur");
		},
		_removeTag: function(tag, shouldTrigger, position) {
			var that = this;
			var state = that._state;
			if (position === undefined) position = tag.index();
			var listView = that.listView;
			var value = listView.value()[position];
			var dataItem = that.listView.selectedDataItems()[position];
			var customIndex = that._customOptions[value];
			var listViewItems = listView.items().toArray();
			var option;
			var listViewItem;
			if (that.trigger(DESELECT, {
				dataItem,
				item: tag
			})) {
				that._close();
				return;
			}
			if (customIndex === undefined && (state === ACCEPT || state === FILTER)) customIndex = that._optionsMap[value];
			var done = function() {
				that.currentTag(null);
				if (shouldTrigger) that._change();
				that._refreshTagListAria();
				that._close();
			};
			if (customIndex === undefined && listView.select().length) {
				that.persistTagList = false;
				listView.select(listView.select()[position]).done(done);
			} else {
				option = that.element[0].children[customIndex];
				if (option) option.selected = false;
				listView.removeAt(position);
				if (listView._removedAddedIndexes) listView._removedAddedIndexes.splice(position, 1);
				listViewItem = listViewItems[customIndex];
				if (listViewItem) {
					$(listViewItem).removeClass("k-selected").attr("aria-selected", false);
					if (that.options.checkboxes) $(listViewItem).find("input.k-checkbox").prop("checked", false).removeClass("k-checked");
				}
				if (that.options.tagMode !== "single") if (that.options.summarizeAfter !== null) that._updateTagListHTML();
				else tag.remove();
				else that._updateTagListHTML();
				done();
			}
			this._placeholder();
		},
		_removeOverflowTag: function(tag, shouldTrigger) {
			const that = this;
			const limit = that.options.summarizeAfter;
			const listView = that.listView;
			const overflowDOMIndices = listView.select().slice(limit);
			if (!overflowDOMIndices.length) {
				if (listView.value().length <= limit) return;
				const overflowValues = listView._values.splice(limit);
				listView._dataItems.splice(limit);
				for (let i = 0; i < overflowValues.length; i++) that._setOption(overflowValues[i], false);
				that.currentTag(null);
				that._updateTagListHTML();
				that._placeholder();
				if (shouldTrigger) that._change();
				that._close();
				return;
			}
			that.persistTagList = false;
			listView.select(overflowDOMIndices).done(function() {
				that.currentTag(null);
				that._placeholder();
				if (shouldTrigger) that._change();
				that._close();
			});
		},
		_tagListClick: function(e) {
			e.preventDefault();
			e.stopPropagation();
			var target = $(e.currentTarget);
			if (target.is("[class*='-i-x-circle']")) {
				this._removeTag(target.closest(CHIP), true);
				this.focus();
			}
		},
		_clearValue: function() {
			var that = this;
			that._clearAllValues();
			that.input.val("");
			that._prev = "";
			if (that._state === FILTER) {
				that._state = ACCEPT;
				if (!that.options.enforceMinLength) that._filterSource();
			}
			that.focus();
			that._hideClear();
		},
		_clearAllValues: function() {
			const that = this;
			that.currentTag(null);
			that.persistTagList = false;
			that._clearSingleTagValue();
			that._updateTagListHTML();
			that._placeholder();
			that._change();
			that._updateSelectAllHeader();
		},
		_removeLastTag: function() {
			const that = this;
			const tag = that.tagList.children(CHIP).last();
			if (tag && tag[0]) {
				const limit = that.options.summarizeAfter;
				if (limit !== null && tag.index() === limit && that.listView.value().length > limit) that._removeOverflowTag(tag, true);
				else that._removeTag(tag, true);
				that._updateSelectAllHeader();
			}
		},
		_clearSingleTagValue: function() {
			const that = this;
			const items = that.dataItems();
			const tags = that.tagList.children(CHIP);
			const persistTagList = that.persistTagList;
			for (let i = 0; i < items.length; i += 1) if (that.trigger(DESELECT, {
				dataItem: items[i],
				item: tags.first()
			})) {
				that._close();
				return;
			}
			if (persistTagList) that.persistTagList = false;
			that.listView.value([]);
			that.persistTagList = persistTagList;
		},
		_focusHandler: function() {
			var input = this.input;
			var active = activeElement();
			if (!(input[0] === active)) this.input.trigger("focus");
		},
		_editable: function(options) {
			var that = this, disable = options.disable, readonly = options.readonly, wrapper = that.wrapper.off(ns), tagList = that.tagList.off(ns), input = that.input.off(ns);
			if (!readonly && !disable) {
				wrapper.removeClass(STATEDISABLED).removeClass(NOCLICKCLASS).on(HOVEREVENTS, that._toggleHover).on("mousedown" + ns + " touchend" + ns, that._wrapperMousedown.bind(that)).on(CLICK, that._focusHandler.bind(that));
				that.input.on(KEYDOWN, that, that._keydown.bind(that)).on("paste" + ns, that._search.bind(that)).on("input" + ns, that._search.bind(that)).on("focus" + ns, that._inputFocus.bind(that)).on("focusout" + ns, that._inputFocusout.bind(that));
				that._clear.on(CLICK + " touchend" + ns, that._clearValue.bind(that));
				input.prop(DISABLED, false).prop(READONLY, false).attr(ARIA_DISABLED, false).attr(ARIA_READONLY, false);
				that.element.prop(DISABLED, false);
				tagList.on(MOUSEENTER, CHIP, function() {
					$(this).addClass(HOVERCLASS);
				}).on(MOUSELEAVE, CHIP, function() {
					$(this).removeClass(HOVERCLASS);
				}).on(CLICK + " touchend" + ns, ".k-chip .k-icon,.k-chip .k-svg-icon", that._tagListClick.bind(that));
				that.list.off(CLICK, ".k-list-sticky-header-item");
				that.list.on(CLICK, ".k-list-sticky-header-item", that._onSelectAllClick.bind(that));
			} else {
				wrapper.toggleClass(STATEDISABLED, disable).toggleClass(NOCLICKCLASS, readonly);
				input.attr(DISABLED, disable).attr(READONLY, readonly).attr(ARIA_DISABLED, disable).attr(ARIA_READONLY, readonly);
				that.element.prop(DISABLED, disable);
				that.list.off(CLICK + " touchend" + ns, ".k-list-sticky-header-item");
			}
		},
		_close: function() {
			var that = this;
			if (that.options.autoClose) that.close();
			else that.popup.position();
		},
		_filterSource: function(filter, force) {
			if (!force) force = this._retrieveData;
			this._retrieveData = false;
			List.fn._filterSource.call(this, filter, force);
		},
		close: function() {
			this._activeItem = null;
			this._selectAllFocused = false;
			this.list.find(".k-list-sticky-header-item").removeClass(FOCUSEDCLASS);
			this.input.removeAttr(ARIA_ACTIVEDESCENDANT);
			this.popup.close();
		},
		open: function() {
			var that = this, filterValue = that.input.val().toLowerCase(), listViewFilter = that.listView.dataSource.filter(), listViewFilterValue = "";
			if (listViewFilter && listViewFilter.filters.length > 0) listViewFilterValue = (listViewFilter.filters[0].value || "").toString().toLowerCase();
			if (that._request) that._retrieveData = false;
			if (that._retrieveData || !that.listView.bound() || that._state === ACCEPT && filterValue !== listViewFilterValue) {
				that._open = true;
				that._state = REBIND;
				that.listView.skipUpdate(true);
				that.persistTagList = that._initialOpen && !that.listView.bound() ? false : true;
				that._filterSource();
				that._focusItem();
			} else if (that._allowOpening()) {
				if (that._initialOpen && !that.options.autoBind && !that.options.virtual && that.options.value && !$.isPlainObject(that.options.value[0])) that.value(that.value() || that._initialValues);
				that.popup._hovered = true;
				that._initialOpen = false;
				that.popup.open({ altTarget: that.wrapper.add(that.element).add(that.input) });
				if (that.options.selectAll) that._updateSelectAllHeader();
				if (that.options.checkboxes) that._syncListCheckboxes();
				that._focusItem();
			}
		},
		toggle: function(toggle) {
			toggle = toggle !== undefined ? toggle : !this.popup.visible();
			this[toggle ? OPEN : CLOSE]();
		},
		refresh: function() {
			this.listView.refresh();
			this._updateTagListHTML();
			this._updateSelectAllHeader();
			this._placeholder();
		},
		_floatCheck: function() {
			if (this.listView) return !(this.value() && this.value().length) && !this.popup.visible();
			return true;
		},
		_listBound: function() {
			var that = this;
			var data = that.dataSource.flatView();
			that._render(data);
			that._renderFooter();
			that._renderNoData();
			that._toggleNoData(!data.length);
			if (that.options.selectAll) {
				that._renderSelectAllHeader();
				that._updateSelectAllHeader();
			}
			if (that.options.checkboxes) that._syncListCheckboxes();
			that._resizePopup();
			if (that._open) {
				that._open = false;
				that.toggle(that._allowOpening());
			}
			if (!that.listView._preventFocus) that.popup.position();
			that._updateItemFocus();
			if (that.options?.virtual?.mapValueTo === "dataItem") that._updateSelectedVirtualDataItemsIndexes();
			if (that._touchScroller) that._touchScroller.reset();
			that._hideBusy();
			that.trigger("dataBound");
		},
		_updateItemFocus: function() {
			var that = this, data = that.dataSource.flatView(), skip = that.listView.skip(), isFirstPage = skip === undefined || skip === 0;
			if (that.listView._preventFocus) return;
			if (data.length && isFirstPage) if (!that.options.highlightFirst) that.listView.focus(-1);
			else that.listView.focusFirst();
		},
		_inputValue: function() {
			var that = this;
			var inputValue = that.filterInput && activeElement() === that.filterInput[0] ? that.filterInput.val() : that.input.val();
			if (that.options.placeholder === inputValue) inputValue = "";
			return inputValue;
		},
		value: function(value) {
			var that = this;
			var listView = that.listView;
			var oldValue = listView.value().slice();
			var maxSelectedItems = that.options.maxSelectedItems;
			var clearFilters = listView.bound() && listView.isFiltered();
			if (value === undefined) return oldValue;
			that.persistTagList = false;
			that.requireValueMapper(that.options, value);
			value = that._normalizeValues(value);
			if (maxSelectedItems !== null && value.length > maxSelectedItems) value = value.slice(0, maxSelectedItems);
			if (clearFilters) that._clearFilter();
			listView.value(value);
			that._old = that._valueBeforeCascade = value.slice();
			if (!clearFilters) that._fetchData();
			that._toggleCloseVisibility();
		},
		_preselect: function(data, value) {
			var that = this;
			if (!isArray(data) && !(data instanceof kendo.data.ObservableArray)) data = [data];
			if ($.isPlainObject(data[0]) || data[0] instanceof kendo.data.ObservableObject || !that.options.dataValueField) {
				that.dataSource.data(data);
				that.value(value || that._initialValues);
				that._retrieveData = true;
			}
		},
		_setOption: function(value, selected) {
			var option = this.element[0].children[this._optionsMap[value]];
			if (option) option.selected = selected;
		},
		_fetchData: function() {
			var that = this;
			var hasItems = !!that.dataSource.view().length;
			if (that.listView.value().length === 0 || that._request) return;
			if (that._retrieveData || !that._fetch && !hasItems) {
				that._fetch = true;
				that._retrieveData = false;
				that.dataSource.read().done(function() {
					that._fetch = false;
				});
			}
		},
		_isBound: function() {
			return this.listView.bound() && !this._retrieveData;
		},
		_dataSource: function() {
			var that = this, element = that.element, options = that.options, dataSource = options.dataSource || {};
			dataSource = isArray(dataSource) ? { data: dataSource } : dataSource;
			dataSource.select = element;
			dataSource.fields = [{ field: options.dataTextField }, { field: options.dataValueField }];
			if (that.dataSource && that._refreshHandler) that._unbindDataSource();
			else {
				that._progressHandler = that._showBusy;
				that._endRequestHandler = that._hideBusy;
				that._errorHandler = function() {
					that._hideBusy();
				};
			}
			that.dataSource = kendo.data.DataSource.create(dataSource).bind(PROGRESS, that._progressHandler).bind("requestEnd", that._endRequestHandler).bind("error", that._errorHandler);
		},
		_reset: function() {
			var that = this, element = that.element, formId = element.attr("form"), form = formId ? $("#" + formId) : element.closest("form");
			if (form[0]) {
				that._resetHandler = function() {
					setTimeout(function() {
						that.value(that._initialValues);
						that._placeholder();
					});
				};
				that._form = form.on("reset", that._resetHandler);
			}
		},
		_initValue: function() {
			var value = this.options.value || this.element.val();
			this._old = this._initialValues = this._normalizeValues(value);
		},
		_normalizeValues: function(value) {
			var that = this;
			if (value === null) value = [];
			else if (value && $.isPlainObject(value)) value = [that._value(value)];
			else if (value && $.isPlainObject(value[0])) value = $.map(value, function(dataItem) {
				return that._value(dataItem);
			});
			else if (!isArray(value) && !(value instanceof ObservableArray)) value = [value];
			else if (isArray(value)) value = value.slice();
			return value;
		},
		_change: function() {
			var that = this, value = that.value();
			if (!compare(value, that._old)) {
				that._old = value.slice();
				that.trigger(CHANGE);
				that.element.trigger(CHANGE);
			}
			that.popup.position();
			that._toggleCloseVisibility();
		},
		_click: function(e) {
			var that = this;
			var item = e.item;
			e.preventDefault();
			that._select(item).done(function() {
				that._activeItem = item;
				that._change();
				that._close();
			});
		},
		_getActiveItem: function() {
			return this._activeItem || $(this.listView.items()[this._getSelectedIndices().length - 1]) || this.listView.focus();
		},
		_getSelectedIndices: function() {
			return this.listView._selectedIndices || this.listView._selectedIndexes;
		},
		_keydown: function(e) {
			var that = this;
			var key = e.keyCode;
			var tag = that._currentTag;
			var listView = that.listView;
			var hasValue = that.input.val();
			var isRtl = kendo.support.isRtl(that.wrapper);
			var visible = that.popup.visible();
			var dir = 0;
			var activeItemIdx;
			var handled = false;
			if (key !== keys.ENTER) this._multipleSelection = false;
			if (key === keys.DOWN) {
				e.preventDefault();
				if (!visible) {
					that.open();
					if (!listView.focus()) listView.focusFirst();
					e.stopPropagation();
					return;
				}
				if (that._selectAllFocused) {
					that.list.find(".k-list-sticky-header-item").removeClass(FOCUSEDCLASS);
					that._selectAllFocused = false;
					that.input.removeAttr(ARIA_ACTIVEDESCENDANT);
					listView.focusFirst();
				} else if (listView.focus()) {
					if (!that._activeItem && e.shiftKey) {
						that._activeItem = listView.focus();
						dir = -1;
					}
					activeItemIdx = listView.getElementIndex(that._getActiveItem().first());
					listView.focusNext();
					if (!listView.focus()) listView.focusLast();
					else if (e.shiftKey && !that.options.virtual) {
						this._multipleSelection = true;
						that._selectRange(activeItemIdx, listView.getElementIndex(listView.focus().first()) + dir);
					}
				} else listView.focusFirst();
				handled = true;
			} else if (key === keys.UP) {
				if (visible) if (that._selectAllFocused) {
					that.list.find(".k-list-sticky-header-item").removeClass(FOCUSEDCLASS);
					that._selectAllFocused = false;
					that.input.removeAttr(ARIA_ACTIVEDESCENDANT);
					that.close();
				} else if (that.options.selectAll && listView.focus() && listView.getElementIndex(listView.focus()) === 0) {
					listView.focus(-1);
					that.list.find(".k-list-sticky-header-item").addClass(FOCUSEDCLASS);
					that._selectAllFocused = true;
					that.input.attr(ARIA_ACTIVEDESCENDANT, that.element[0].id + "_selectAll");
				} else {
					if (!that._activeItem && e.shiftKey) {
						that._activeItem = listView.focus();
						dir = 1;
					}
					activeItemIdx = listView.getElementIndex(that._getActiveItem().first());
					listView.focusPrev();
					if (!listView.focus()) that.close();
					else if (e.shiftKey && !that.options.virtual) {
						this._multipleSelection = true;
						that._selectRange(activeItemIdx, listView.getElementIndex(listView.focus().first()) + dir);
					}
				}
				handled = true;
				e.preventDefault();
			} else if (key === keys.LEFT && !isRtl || key === keys.RIGHT && isRtl) {
				if (!hasValue) {
					tag = tag ? tag.prev(CHIP) : that.tagList.children(CHIP).last();
					if (tag[0]) that.currentTag(tag);
				}
				handled = true;
			} else if (key === keys.RIGHT && !isRtl || key === keys.LEFT && isRtl) {
				if (!hasValue && tag) {
					tag = tag.next(CHIP);
					that.currentTag(tag[0] ? tag : null);
				}
				handled = true;
			} else if (e.ctrlKey && !e.altKey && key === keys.A && visible && !that.options.virtual) {
				this._multipleSelection = true;
				if (this._getSelectedIndices().length === listView.items().length) that._activeItem = null;
				if (listView.items().length) {
					that._selectRange(0, listView.items().length - 1);
					that._updateSelectAllHeader();
				}
				handled = true;
			} else if (key === keys.ENTER && visible) if (that._selectAllFocused) {
				that._onSelectAllClick({ preventDefault: $.noop });
				e.preventDefault();
				handled = true;
			} else {
				if (!listView.focus()) {
					e.stopPropagation();
					return;
				}
				e.preventDefault();
				if (this._multipleSelection) {
					this._multipleSelection = false;
					if (listView.focus().hasClass(SELECTEDCLASS)) {
						that._close();
						e.stopPropagation();
						return;
					}
				}
				that._select(listView.focus()).done(function() {
					that._change();
					that._close();
				});
				handled = true;
			}
			else if (key === keys.SPACEBAR && e.ctrlKey && visible && that._selectAllFocused) {
				that._onSelectAllClick({ preventDefault: $.noop });
				e.preventDefault();
				handled = true;
			} else if (key === keys.SPACEBAR && e.ctrlKey && visible && !that._selectAllFocused) {
				if (that._activeItem && listView.focus() && listView.focus()[0] === that._activeItem[0]) that._activeItem = null;
				if (!$(listView.focus()).hasClass(SELECTEDCLASS)) that._activeItem = listView.focus();
				that._select(listView.focus()).done(function() {
					that._change();
				});
				handled = true;
				e.preventDefault();
			} else if (key === keys.SPACEBAR && e.shiftKey && visible && !that.options.virtual) {
				var activeIndex = listView.getElementIndex(that._getActiveItem());
				var currentIndex = listView.getElementIndex(listView.focus());
				if (activeIndex !== undefined && currentIndex !== undefined) that._selectRange(activeIndex, currentIndex);
				handled = true;
				e.preventDefault();
			} else if (key === keys.ESC) {
				if (visible) e.preventDefault();
				else if (that.options.tagMode === "single") {
					var lastPos = listView.value().length - 1;
					if (lastPos >= 0) {
						var lastTag = that.tagList.children(CHIP).last();
						that._removeTag(lastTag, false, lastPos);
						that._change();
					}
				} else that._clearAllValues();
				that.close();
				handled = true;
			} else if (key === keys.HOME) {
				if (visible) if (!listView.focus()) that.close();
				else {
					if (e.ctrlKey && e.shiftKey && !that.options.virtual) that._selectRange(listView.getElementIndex(listView.focus()[0]), 0);
					listView.focusFirst();
				}
				else if (!hasValue) {
					tag = that.tagList.children(CHIP).first()[0];
					if (tag) that.currentTag($(tag));
				}
				handled = true;
			} else if (key === keys.END) {
				if (visible) if (!listView.focus()) that.close();
				else {
					if (e.ctrlKey && e.shiftKey && !that.options.virtual) that._selectRange(listView.getElementIndex(listView.focus()[0]), listView.items().length - 1);
					listView.focusLast();
				}
				else if (!hasValue) {
					tag = that.tagList.children(CHIP).last()[0];
					if (tag) that.currentTag($(tag));
				}
				handled = true;
			} else if (key === keys.DELETE && !hasValue) {
				that._state = ACCEPT;
				if (that.options.tagMode === "single") {
					that._clearAllValues();
					that._close();
					e.stopPropagation();
					return;
				}
				if (tag && tag[0]) {
					const limit = that.options.summarizeAfter;
					if (limit !== null && tag.index() === limit && listView.value().length > limit) that._removeOverflowTag(tag, true);
					else that._removeTag(tag, true);
					that._updateSelectAllHeader();
				}
				handled = true;
			} else if (key === keys.BACKSPACE && !hasValue && that.options.tagMode === "single") {
				that._state = ACCEPT;
				that._clearAllValues();
				that._close();
				e.stopPropagation();
				return;
			} else if (key === keys.BACKSPACE && !hasValue) {
				that._state = ACCEPT;
				if (!tag) that._removeLastTag();
				else if (tag[0]) {
					const limit = that.options.summarizeAfter;
					if (limit !== null && tag.index() === limit && listView.value().length > limit) that._removeOverflowTag(tag, true);
					else that._removeTag(tag, true);
					that._updateSelectAllHeader();
				}
				handled = true;
			} else if (that.popup.visible() && (key === keys.PAGEDOWN || key === keys.PAGEUP)) {
				e.preventDefault();
				var direction = key === keys.PAGEDOWN ? 1 : -1;
				listView.scrollWith(direction * listView.screenHeight());
				handled = true;
			} else {
				clearTimeout(that._typingTimeout);
				that._search();
				handled = true;
			}
			if (handled) e.stopPropagation();
		},
		_placeholder: function() {
			const that = this;
			const input = that.input;
			const active = activeElement();
			const isActive = input[0] === active;
			if (this.listView.selectedDataItems().length > 0) input.removeAttr("placeholder");
			else input.attr("placeholder", that.options.placeholder);
			if (!isActive || that.options.autoClose) input.val("");
			that._prev = input.val();
		},
		_option: function(dataValue, dataText, selected) {
			var option = "<option";
			if (dataValue !== undefined) {
				dataValue += "";
				if (dataValue.indexOf("\"") !== -1) dataValue = dataValue.replace(quotRegExp, "&quot;");
				option += " value=\"" + dataValue + "\"";
			}
			if (selected) option += " selected";
			option += ">";
			if (dataText !== undefined) option += kendo.htmlEncode(dataText);
			return option += "</option>";
		},
		_render: function(data) {
			var selectedItems = this.listView.selectedDataItems();
			var values = this.listView.value();
			var length = data.length;
			var selectedIndex;
			var options = "";
			var dataItem;
			var value;
			var idx;
			if (values.length !== selectedItems.length) selectedItems = this._buildSelectedItems(values);
			var custom = {};
			var optionsMap = {};
			for (idx = 0; idx < length; idx++) {
				dataItem = data[idx];
				value = this._value(dataItem);
				selectedIndex = this._selectedItemIndex(value, selectedItems);
				if (selectedIndex !== -1) selectedItems.splice(selectedIndex, 1);
				optionsMap[value] = idx;
				options += this._option(value, this._text(dataItem), selectedIndex !== -1);
			}
			if (selectedItems.length) for (idx = 0; idx < selectedItems.length; idx++) {
				dataItem = selectedItems[idx];
				value = this._value(dataItem);
				custom[value] = length;
				optionsMap[value] = length;
				length += 1;
				options += this._option(value, this._text(dataItem), true);
			}
			this._customOptions = custom;
			this._optionsMap = optionsMap;
			this.element.html(options);
		},
		_buildSelectedItems: function(values) {
			var valueField = this.options.dataValueField;
			var textField = this.options.dataTextField;
			var result = [];
			var item;
			for (var idx = 0; idx < values.length; idx++) {
				item = {};
				item[valueField] = values[idx];
				item[textField] = values[idx];
				result.push(item);
			}
			return result;
		},
		_selectedItemIndex: function(value, selectedItems) {
			var valueGetter = this._value;
			var idx = 0;
			for (; idx < selectedItems.length; idx++) if (value === valueGetter(selectedItems[idx])) return idx;
			return -1;
		},
		_search: function(noDelay) {
			let that = this;
			if (noDelay === true) {
				that._performSearch();
				return;
			}
			clearTimeout(that._typingTimeout);
			that._typingTimeout = setTimeout(function() {
				that._performSearch();
			}, that.options.delay);
		},
		_performSearch: function() {
			var that = this, value = that._inputValue();
			if (that._prev !== value) {
				that._prev = value;
				that.search(value);
				that._toggleCloseVisibility();
			}
		},
		_toggleCloseVisibility: function() {
			if (this.value().length || this.input.val() && this.input.val() !== this.options.placeholder) this._showClear();
			else this._hideClear();
		},
		_allowOpening: function() {
			return this._allowSelection() && List.fn._allowOpening.call(this);
		},
		_allowSelection: function() {
			var max = this.options.maxSelectedItems;
			return max === null || max > this.listView.value().length;
		},
		updatePersistTagList: function(added, removed) {
			if (this.persistTagList.added && this.persistTagList.added.length === removed.length && this.persistTagList.removed && this.persistTagList.removed.length === added.length) this.persistTagList = false;
			else {
				this.listView._removedAddedIndexes = this._old.slice();
				this.persistTagList = {
					added,
					removed
				};
			}
		},
		_selectValue: function(added, removed) {
			var that = this;
			var total = that.dataSource.total();
			var tagList = that.tagList;
			var getter = that._value;
			var removedItem;
			var addedItem;
			var idx;
			if (this.persistTagList) {
				this.updatePersistTagList(added, removed);
				that._refreshTagListAria();
				return;
			}
			if (that._effectiveTagMode() === "multiple") if (that.options.summarizeAfter !== null) {
				that._updateTagListHTML();
				for (idx = removed.length - 1; idx > -1; idx--) that._setOption(getter(removed[idx].dataItem), false);
				for (idx = 0; idx < added.length; idx++) that._setOption(getter(added[idx].dataItem), true);
			} else {
				for (idx = removed.length - 1; idx > -1; idx--) {
					removedItem = removed[idx];
					if (tagList.children(CHIP).length) {
						tagList[0].removeChild(tagList[0].children[removedItem.position]);
						that._setOption(getter(removedItem.dataItem), false);
					}
				}
				for (idx = 0; idx < added.length; idx++) {
					addedItem = added[idx];
					that.tagList.append(that.tagTemplate(addedItem.dataItem));
					that._setOption(getter(addedItem.dataItem), true);
				}
				kendo.applyStylesFromKendoAttributes(that.tagList, ["background-color"]);
			}
			else {
				if (!that._maxTotal || that._maxTotal < total) that._maxTotal = total;
				this._updateTagListHTML();
				for (idx = removed.length - 1; idx > -1; idx--) that._setOption(getter(removed[idx].dataItem), false);
				for (idx = 0; idx < added.length; idx++) that._setOption(getter(added[idx].dataItem), true);
			}
			that._refreshTagListAria();
			that._refreshFloatingLabel();
			that._placeholder();
			if (that.options.selectAll) that._updateSelectAllHeader();
			if (that.options.checkboxes) that._syncListCheckboxes();
		},
		_refreshTagListAria: function() {
			var that = this;
			html.renderChipList(that.tagList, $.extend({ selectable: that.value().length === 0 ? "none" : "multiple" }, that.options));
		},
		_updateTagListHTML: function() {
			const that = this;
			const total = that.dataSource.total();
			const tagList = that.tagList;
			const selectedCount = that.listView.value().length;
			tagList.children(CHIP).each(function(index, tag) {
				$(tag).remove();
			});
			if (that.options.summarizeAfter !== null && selectedCount >= that.options.summarizeAfter) {
				const allDataItems = that.dataItems();
				const limit = that.options.summarizeAfter;
				const visibleDataItems = allDataItems.slice(0, limit);
				const overflowCount = allDataItems.length - limit;
				for (const dataItem of visibleDataItems) that.tagList.append(that.tagTemplate(dataItem));
				if (overflowCount > 0) that.tagList.append(html.renderChip("<span unselectable=\"on\"></span>", $.extend({}, that.options, {
					enabled: true,
					text: "+" + overflowCount + " " + encode(that.options.messages.singleTag),
					attr: {
						unselectable: "on",
						"aria-selected": true,
						role: "option",
						"aria-keyshortcuts": "Enter"
					},
					removable: false,
					removableAttr: {},
					icon: "chevron-down",
					iconAttr: {
						unselectable: "on",
						"aria-hidden": true,
						"aria-label": "open"
					}
				})));
				kendo.applyStylesFromKendoAttributes(that.tagList, ["background-color"]);
			} else if (that._effectiveTagMode() === "multiple") {
				const allDataItems = that.dataItems();
				for (let i = 0; i < allDataItems.length; i++) that.tagList.append(that.tagTemplate(allDataItems[i]));
				kendo.applyStylesFromKendoAttributes(that.tagList, ["background-color"]);
			} else {
				const values = that.value();
				if (!values.length) {
					that._refreshTagListAria();
					return;
				}
				that.tagList.append(that.tagTemplate({
					values,
					dataItems: that.dataItems(),
					maxTotal: that._maxTotal,
					currentTotal: total
				}));
				kendo.applyStylesFromKendoAttributes(that.tagList, ["background-color"]);
			}
			that._refreshTagListAria();
		},
		_select: function(candidate) {
			var resolved = $.Deferred().resolve();
			if (!candidate) return resolved;
			var that = this;
			var listView = that.listView;
			var dataItem = listView.dataItemByIndex(listView.getElementIndex(candidate));
			var isSelected = that.options.checkboxes ? candidate.find("input.k-checkbox").prop("checked") : candidate.hasClass("k-selected");
			if (that._state === REBIND) that._state = "";
			if (!that._allowSelection() && !isSelected) return resolved;
			if (that.trigger(isSelected ? DESELECT : SELECT, {
				dataItem,
				item: candidate
			})) {
				that._close();
				return resolved;
			}
			if (isSelected && that.options.virtual && that.options.checkboxes) {
				that._deselectItemDirect(candidate, dataItem);
				return resolved;
			}
			that.persistTagList = false;
			return listView.select(candidate).done(function() {
				that._placeholder();
				if (that._state === FILTER) {
					that._state = ACCEPT;
					listView.skipUpdate(true);
				}
			});
		},
		_selectIndices: function(indices) {
			let listView = this.listView;
			let that = this;
			listView.select(indices).done(function() {
				indices.forEach(function(index) {
					var dataItem = listView.dataItemByIndex(index);
					var candidate = listView.items()[index];
					var isSelected = $(candidate).hasClass("k-selected");
					that.trigger(isSelected ? SELECT : DESELECT, {
						dataItem,
						item: $(candidate)
					});
				});
				that._change();
			});
		},
		_selectRange: function(startIndex, endIndex) {
			var that = this;
			var maxSelectedItems = this.options.maxSelectedItems;
			var indices = this._getSelectedIndices().slice();
			var indicesToSelect = [];
			var i;
			if (indices.length - 1 === endIndex - startIndex) return that._selectIndices(indices);
			if (startIndex < endIndex) for (i = startIndex; i <= endIndex; i++) indicesToSelect.push(i);
			else for (i = startIndex; i >= endIndex; i--) indicesToSelect.push(i);
			if (maxSelectedItems !== null && indicesToSelect.length > maxSelectedItems) indicesToSelect = indicesToSelect.slice(0, maxSelectedItems);
			for (i = 0; i < indicesToSelect.length; i++) {
				var index = indicesToSelect[i];
				if (this._getSelectedIndices().indexOf(index) == -1) indices.push(index);
				else indices.splice(indices.indexOf(index), 1);
			}
			if (!indices.length) return;
			that.persistTagList = false;
			return that._selectIndices(indices);
		},
		_input: function() {
			var that = this;
			var element = that.element;
			var accessKey = element[0].accessKey;
			var input = that._inputValuesContainer.children("input.k-input-inner");
			if (!input[0]) input = $("<input class=\"k-input-inner\" />").appendTo(that._inputValuesContainer);
			element.removeAttr("accesskey");
			input.attr("data-validate", "false");
			input.attr("inputmode", that.options.inputMode);
			that._focused = that.input = input.attr({
				"autocomplete": AUTOCOMPLETEVALUE,
				"title": element[0].title
			});
			input.attr("placeholder", that.options.placeholder);
			if (accessKey) that._focused.attr("accesskey", accessKey);
		},
		_inputValuesContainer: function() {
			var that = this, inputValuesContainer = that.wrapper.children(".k-input-values");
			if (!inputValuesContainer[0]) inputValuesContainer = $("<div class=\"k-input-values\"></div>").appendTo(that.wrapper);
			that._inputValuesContainer = inputValuesContainer;
		},
		_tagList: function() {
			var that = this, options = that.options, tagList = that._inputValuesContainer.children(".k-chip-list");
			if (!tagList[0]) tagList = $(html.renderChipList("<div unselectable=\"on\" class=\"k-selection-multiple\" />", $.extend({ selectable: "none" }, options))).appendTo(that._inputValuesContainer);
			that.tagList = tagList;
		},
		_tagTemplate: function() {
			var that = this;
			var options = that.options;
			var tagTemplate = options.tagTemplate;
			var hasDataSource = options.dataSource;
			var isMultiple = options.tagMode === "multiple";
			var singleTag = options.messages.singleTag;
			var defaultTemplate;
			var multipleTemplateFunc;
			var singleTemplateFunc;
			if (that.element[0].length && !hasDataSource) {
				options.dataTextField = options.dataTextField || "text";
				options.dataValueField = options.dataValueField || "value";
			}
			multipleTemplateFunc = (data) => encode(kendo.getter(options.dataTextField)(data));
			singleTemplateFunc = ({ values }) => `${values.length} ${encode(singleTag)}`;
			defaultTemplate = isMultiple ? multipleTemplateFunc : singleTemplateFunc;
			that.tagTextTemplate = tagTemplate = tagTemplate ? kendo.template(tagTemplate) : defaultTemplate;
			that.tagTemplate = function(data) {
				return html.renderChip("<span unselectable=\"on\"></span>", $.extend({}, options, {
					enabled: true,
					text: tagTemplate(data),
					attr: {
						unselectable: "on",
						"aria-selected": true,
						role: "option",
						"aria-keyshortcuts": isMultiple ? "Enter Delete" : "Enter"
					},
					removable: isMultiple,
					removableAttr: {
						unselectable: "on",
						"aria-hidden": true,
						"aria-label": that.options.messages.deleteTag,
						title: that.options.messages.deleteTag
					},
					icon: !isMultiple ? "chevron-down" : "",
					iconAttr: {
						unselectable: "on",
						"aria-hidden": true,
						"aria-label": "open"
					}
				}));
			};
		},
		_popup: function() {
			List.fn._popup.call(this);
			this.popup.element.addClass("k-multiselect-popup");
		},
		_clearButton: function() {
			List.fn._clearButton.call(this);
			if (this.options.clearButton) this._clear.insertAfter(this._inputValuesContainer);
		},
		_arrowButton: function() {
			var arrowTitle = encode(this.options.messages.downArrow), arrow = $(html.renderButton("<button type=\"button\" aria-label=\"" + arrowTitle + "\" class=\"k-input-button\"></button>", $.extend({}, this.options, {
				icon: "chevron-down",
				rounded: null
			})));
			if (this._arrow) {
				this._arrow.remove();
				this._arrow = null;
			}
			if (this.options.downArrow) {
				this._arrow = arrow.attr({ "tabIndex": -1 });
				this._arrow.appendTo(this.wrapper);
			}
		},
		_textContainer: function() {
			var computedStyles = kendo.getComputedStyles(this.input[0], styles);
			computedStyles.position = "absolute";
			computedStyles.visibility = "hidden";
			computedStyles.top = -3333;
			computedStyles.left = -3333;
			this._span = $("<span/>").css(computedStyles).appendTo(this.wrapper);
		},
		_wrapper: function() {
			var that = this, element = that.element, wrapper = element.parent("span.k-multiselect");
			if (!wrapper[0]) {
				wrapper = element.wrap("<span class=\"k-multiselect k-input\" unselectable=\"on\" />").parent();
				wrapper[0].style.cssText = element[0].style.cssText;
			}
			that.wrapper = wrapper.addClass(element[0].className).removeClass("input-validation-error").css("display", "");
		},
		_renderSelectAllHeader: function() {
			const that = this;
			that._removeSelectAllHeader();
			const itemId = that.element[0].id + "_selectAll";
			const label = that.options.messages.selectAll;
			const checkboxHtml = that.options.checkboxes ? "<span class=\"k-checkbox-wrap\"><input class=\"k-checkbox\" type=\"checkbox\" aria-label=\"" + encode(label) + "\"></span>" : "";
			const roleAttr = !that.options.checkboxes ? " role=\"button\"" : "";
			const headerHtml = "<div class=\"k-list-sticky-header\"><div class=\"k-list-sticky-header-item\" id=\"" + itemId + "\"" + roleAttr + ">" + checkboxHtml + "<span class=\"k-list-item-text\">" + encode(label) + "</span></div></div>";
			that.list.prepend(headerHtml);
		},
		_removeSelectAllHeader: function() {
			this.list.children(".k-list-sticky-header").remove();
		},
		_syncListCheckboxes: function() {
			this.listView.items().each(function() {
				const li = $(this);
				const isSelected = li.attr("aria-selected") === "true";
				li.find("input.k-checkbox").toggleClass("k-checked", isSelected).prop("checked", isSelected);
			});
		},
		_selectAllState: function() {
			const that = this;
			const selectedCount = that._listSelectedCount();
			const total = that.dataSource.total();
			if (selectedCount === 0) return "unchecked";
			if (selectedCount >= total) return "checked";
			return "indeterminate";
		},
		_updateSelectAllHeader: function() {
			const that = this;
			if (!that.options.selectAll) return;
			const header = that.list.find(".k-list-sticky-header");
			if (!header.length) return;
			const state = that._selectAllState();
			if (that.options.checkboxes) {
				const checkbox = header.find("input.k-checkbox");
				const ariaChecked = state === "checked" ? "true" : state === "indeterminate" ? "mixed" : "false";
				checkbox.toggleClass("k-checked", state === "checked").toggleClass("k-indeterminate", state === "indeterminate").prop("checked", state === "checked").attr("aria-checked", ariaChecked);
			} else header.find(".k-list-sticky-header-item").toggleClass(SELECTEDCLASS, state === "checked");
		},
		_focusSelectAllHeader: function() {
			const that = this;
			const headerItem = that.list.find(".k-list-sticky-header-item");
			if (!headerItem.length) return;
			that.listView.focus(-1);
			headerItem.addClass(FOCUSEDCLASS);
			that._selectAllFocused = true;
			that.input.attr(ARIA_ACTIVEDESCENDANT, that.element[0].id + "_selectAll");
		},
		_onSelectAllClick: function(e) {
			const that = this;
			e.preventDefault();
			const state = that._selectAllState();
			if (that.trigger(SELECTALL, { checked: state !== "checked" })) return;
			if (state === "checked") {
				that._deselectAllItems();
				that._updateTagListHTML();
				that._placeholder();
				that._updateSelectAllHeader();
				that._change();
				that._close();
				that._clearFilterOnAutoClose();
				if (!that.options.autoClose) that._focusSelectAllHeader();
			} else that._selectAllItems().done(function() {
				that._change();
				that._close();
				that._clearFilterOnAutoClose();
				if (!that.options.autoClose) that._focusSelectAllHeader();
			});
		},
		_clearFilterOnAutoClose: function() {
			const that = this;
			if (!that.options.autoClose) return;
			if (that._state === FILTER) {
				that._state = ACCEPT;
				that.listView.skipUpdate(true);
			}
			if (that.listView.bound() && that.listView.isFiltered()) {
				that.persistTagList = true;
				that._clearFilter();
			}
		},
		_deselectItemDirect: function(candidate, dataItem) {
			const that = this;
			const listView = that.listView;
			const valueGetter = that._value;
			const val = valueGetter(dataItem);
			const valIdx = listView._values.indexOf(val);
			if (valIdx > -1) {
				listView._values.splice(valIdx, 1);
				listView._selectedDataItems.splice(valIdx, 1);
				listView._selectedIndexes.splice(valIdx, 1);
			}
			if (that.options.checkboxes) {
				candidate.find("input.k-checkbox").prop("checked", false).removeClass("k-checked");
				candidate.attr("aria-selected", false);
			}
			if (that._effectiveTagMode() === "multiple") {
				if (valIdx > -1) {
					that.tagList.children(CHIP).eq(valIdx).remove();
					that._setOption(val, false);
				}
			} else that._updateTagListHTML();
			that._placeholder();
			that._updateSelectAllHeader();
		},
		_selectAllItems: function() {
			const that = this;
			const listView = that.listView;
			const flatView = that.dataSource.flatView();
			const currentValues = listView.value();
			const valueGetter = that._value;
			const maxSelectedItems = that.options.maxSelectedItems;
			const isVirtual = !!that.options.virtual;
			const skip = isVirtual ? listView.skip() || 0 : 0;
			const total = isVirtual ? that.dataSource.total() : flatView.length;
			const currentValueSet = {};
			for (let i = 0; i < currentValues.length; i++) currentValueSet[currentValues[i]] = true;
			let indices = [];
			for (let i = 0; i < flatView.length; i++) {
				const absIdx = skip + i;
				if (absIdx < total && !currentValueSet[valueGetter(flatView[i])]) indices.push(absIdx);
			}
			if (maxSelectedItems !== null) {
				const available = maxSelectedItems - currentValues.length;
				if (available <= 0) return $.Deferred().resolve();
				indices = indices.slice(0, available);
			}
			if (!indices.length) return $.Deferred().resolve();
			that.persistTagList = false;
			if (isVirtual) listView._preventFocus = true;
			return listView.select(indices).done(function() {
				if (isVirtual) listView._preventFocus = false;
				const currentSkip = listView.skip() || 0;
				for (let k = 0; k < indices.length; k++) {
					const idx = indices[k];
					const dataItem = listView.dataItemByIndex(idx);
					const domIdx = idx - currentSkip;
					const candidate = $(listView.items()[domIdx]);
					that.trigger(SELECT, {
						dataItem,
						item: candidate
					});
				}
			});
		},
		_deselectAllItems: function() {
			const that = this;
			const listView = that.listView;
			const flatView = that.dataSource.flatView();
			const valueGetter = that._value;
			const currentValues = listView.value();
			const flatViewValueSet = {};
			const remainingValues = [];
			if (that.options.virtual) {
				that.persistTagList = false;
				listView._values = [];
				listView._selectedDataItems = [];
				listView._selectedIndexes = [];
				listView.value([]);
				listView.items().each(function() {
					const li = $(this);
					li.attr("aria-selected", "false").removeClass("k-selected");
					li.find("input.k-checkbox").prop("checked", false).removeClass("k-checked");
				});
				return;
			}
			for (let i = 0; i < flatView.length; i++) flatViewValueSet[valueGetter(flatView[i])] = true;
			for (let i = 0; i < currentValues.length; i++) if (!flatViewValueSet[currentValues[i]]) remainingValues.push(currentValues[i]);
			const remainingDataItems = listView.selectedDataItems().filter(function(dataItem) {
				return !flatViewValueSet[valueGetter(dataItem)];
			});
			that.persistTagList = false;
			listView.value([]);
			if (remainingDataItems.length) listView.selectedDataItems(remainingDataItems);
			else if (remainingValues.length) listView.setValue(remainingValues);
		},
		_listSelectedCount: function() {
			if (this.options.virtual) return this.listView.value().length;
			return Math.max(0, this.listView.value().length - Object.keys(this._customOptions).length);
		},
		_effectiveTagMode: function() {
			if (this.options.summarizeAfter !== null && this._listSelectedCount() >= this.options.summarizeAfter) return "single";
			return this.options.tagMode;
		},
		_closeHandler: function(e) {
			if (this.trigger(CLOSE)) e.preventDefault();
			else {
				this.input.attr(ARIA_EXPANDED, false);
				this.ul.attr(ARIA_HIDDEN, true);
				if (this._selectAllFocused) {
					this.list.find(".k-list-sticky-header-item").removeClass(FOCUSEDCLASS);
					this._selectAllFocused = false;
					this.input.removeAttr(ARIA_ACTIVEDESCENDANT);
				}
			}
		},
		_openHandler: function(e) {
			this._adjustListWidth();
			if (this.trigger(OPEN)) e.preventDefault();
			else {
				this.input.attr(ARIA_EXPANDED, true);
				this.ul.attr(ARIA_HIDDEN, false);
			}
		}
	});
	function compare(a, b) {
		var length;
		if (a === null || b === null) return a === b;
		length = a.length;
		if (length !== b.length) return false;
		while (length--) if (a[length] !== b[length]) return false;
		return true;
	}
	ui.plugin(MultiSelect);
	kendo.cssProperties.registerPrefix("MultiSelect", "k-input-");
	kendo.cssProperties.registerValues("MultiSelect", [{
		prop: "rounded",
		values: kendo.cssProperties.roundedValues.concat([["full", "full"]])
	}]);
})(window.kendo.jQuery);
var kendo_multiselect_default = kendo;
//#endregion
exports.__meta__ = __meta__;
exports.default = kendo_multiselect_default;