{"version":3,"file":"kendo.dropdownlist.min.js","sources":["kendo.dropdownlist.js"],"sourcesContent":["(function(f, define){\n define('kendo.dropdownlist',[ \"./kendo.list\", \"./kendo.mobile.scroller\", \"./kendo.virtuallist\", \"./kendo.html.button\" ], f);\n})(function(){\n\nvar __meta__ = { // jshint ignore:line\n id: \"dropdownlist\",\n name: \"DropDownList\",\n category: \"web\",\n description: \"The DropDownList widget displays a list of values and allows the selection of a single value from the list.\",\n depends: [ \"list\", \"html.button\" ],\n features: [ {\n id: \"mobile-scroller\",\n name: \"Mobile scroller\",\n description: \"Support for kinetic scrolling in mobile device\",\n depends: [ \"mobile.scroller\" ]\n }, {\n id: \"virtualization\",\n name: \"VirtualList\",\n description: \"Support for virtualization\",\n depends: [ \"virtuallist\" ]\n } ]\n};\n\n(function($, undefined) {\n var kendo = window.kendo,\n ui = kendo.ui,\n html = kendo.html,\n List = ui.List,\n Select = ui.Select,\n support = kendo.support,\n activeElement = kendo._activeElement,\n ObservableObject = kendo.data.ObservableObject,\n keys = kendo.keys,\n ns = \".kendoDropDownList\",\n nsFocusEvent = ns + \"FocusEvent\",\n DISABLED = \"disabled\",\n READONLY = \"readonly\",\n CHANGE = \"change\",\n FOCUSED = \"k-focus\",\n STATEDISABLED = \"k-disabled\",\n ARIA_DISABLED = \"aria-disabled\",\n ARIA_READONLY = \"aria-readonly\",\n CLICKEVENTS = \"click\" + ns + \" touchend\" + ns,\n HOVEREVENTS = \"mouseenter\" + ns + \" mouseleave\" + ns,\n TABINDEX = \"tabindex\",\n STATE_FILTER = \"filter\",\n STATE_ACCEPT = \"accept\",\n MSG_INVALID_OPTION_LABEL = \"The `optionLabel` option is not valid due to missing fields. Define a custom optionLabel as shown here http://docs.telerik.com/kendo-ui/api/javascript/ui/dropdownlist#configuration-optionLabel\",\n OPEN = \"open\",\n CLOSE = \"close\";\n\n var DropDownList = Select.extend( {\n init: function(element, options) {\n var that = this;\n var index = options && options.index;\n var optionLabel, text, disabled;\n\n that.ns = ns;\n options = Array.isArray(options) ? { dataSource: options } : options;\n\n Select.fn.init.call(that, element, options);\n\n options = that.options;\n element = that.element.on(\"focus\" + ns, that._focusHandler.bind(that));\n\n that._focusInputHandler = that._focusInput.bind(that);\n\n that.optionLabel = $();\n that._optionLabel();\n\n that._inputTemplate();\n\n that._reset();\n\n that._prev = \"\";\n that._word = \"\";\n\n that._wrapper();\n\n that._tabindex();\n that.wrapper.data(TABINDEX, that.wrapper.attr(TABINDEX));\n\n that._span();\n\n that._popup();\n\n that._mobile();\n\n that._dataSource();\n\n that._ignoreCase();\n\n that._filterHeader();\n\n that._aria();\n\n //should read changed value of closed dropdownlist\n if (kendo.support.browser.chrome) {\n that.wrapper.attr(\"aria-live\", \"polite\");\n }\n\n that._enable();\n\n that._attachFocusHandlers();\n\n that._oldIndex = that.selectedIndex = -1;\n\n if (index !== undefined) {\n options.index = index;\n }\n\n that._initialIndex = options.index;\n\n that.requireValueMapper(that.options);\n that._initList();\n that.listView.one(\"dataBound\", that._attachAriaActiveDescendant.bind(that));\n\n that._cascade();\n\n that.one(\"set\", function(e) {\n if (!e.sender.listView.bound() && that.hasOptionLabel()) {\n that._textAccessor(that._optionLabelText());\n }\n });\n\n if (options.autoBind) {\n that.dataSource.fetch();\n } else if (that.selectedIndex === -1) { //selectedIndex !== -1 when cascade functionality happens instantly\n text = options.text || \"\";\n if (!text) {\n optionLabel = options.optionLabel;\n\n if (optionLabel && options.index === 0) {\n text = optionLabel;\n } else if (that._isSelect) {\n text = element.children(\":selected\").text();\n }\n }\n\n that._textAccessor(text);\n }\n\n disabled = $(that.element).parents(\"fieldset\").is(':disabled');\n\n if (disabled) {\n that.enable(false);\n }\n\n that.listView.bind(\"click\", function(e) { e.preventDefault(); });\n\n kendo.notify(that);\n that._applyCssClasses();\n },\n\n options: {\n name: \"DropDownList\",\n enabled: true,\n autoBind: true,\n index: 0,\n text: null,\n value: null,\n delay: 500,\n height: 200,\n dataTextField: \"\",\n dataValueField: \"\",\n optionLabel: \"\",\n cascadeFrom: \"\",\n cascadeFromField: \"\",\n cascadeFromParentField: \"\",\n ignoreCase: true,\n animation: {},\n filter: \"none\",\n minLength: 1,\n enforceMinLength: false,\n virtual: false,\n template: null,\n valueTemplate: null,\n optionLabelTemplate: null,\n groupTemplate: \"#:data#\",\n fixedGroupTemplate: \"#:data#\",\n autoWidth: false,\n popup: null,\n filterTitle: null,\n size: \"medium\",\n fillMode: \"solid\",\n rounded: \"medium\"\n },\n\n events: [\n \"open\",\n \"close\",\n CHANGE,\n \"select\",\n \"filtering\",\n \"dataBinding\",\n \"dataBound\",\n \"cascade\",\n \"set\",\n \"kendoKeydown\"\n ],\n\n setOptions: function(options) {\n Select.fn.setOptions.call(this, options);\n\n this.listView.setOptions(this._listOptions(options));\n\n this._optionLabel();\n this._inputTemplate();\n this._accessors();\n this._filterHeader();\n this._enable();\n this._aria();\n\n if (!this.value() && this.hasOptionLabel()) {\n this.select(0);\n }\n },\n\n destroy: function() {\n var that = this;\n\n Select.fn.destroy.call(that);\n\n that.wrapper.off(ns);\n that.wrapper.off(nsFocusEvent);\n that.element.off(ns);\n\n that._arrow.off();\n that._arrow = null;\n that._arrowIcon = null;\n\n that.optionLabel.off();\n\n if(that.filterInput){\n that.filterInput.off(nsFocusEvent);\n }\n },\n\n open: function() {\n var that = this;\n var isFiltered = that.dataSource.filter() ? that.dataSource.filter().filters.length > 0 : false;\n var listView = this.listView;\n\n if (that.popup.visible()) {\n return;\n }\n\n if (!that.listView.bound() || that._state === STATE_ACCEPT) {\n that._open = true;\n that._state = \"rebind\";\n\n if (that.filterInput) {\n that.filterInput.val(\"\");\n that._prev = \"\";\n }\n\n if (that.filterInput && that.options.minLength !== 1 && !isFiltered) {\n that.refresh();\n that.popup.one(\"activate\", that._focusInputHandler);\n that.wrapper.attr(\"aria-activedescendant\", listView._optionID);\n that.popup.open();\n that._resizeFilterInput();\n } else {\n that._filterSource();\n }\n } else if (that._allowOpening()) {\n that._focusFilter = true;\n that.popup.one(\"activate\", that._focusInputHandler);\n // In some cases when the popup is opened resize is triggered which will cause it to close\n // Setting the below flag will prevent this from happening\n that.popup._hovered = true;\n that.wrapper.attr(\"aria-activedescendant\", listView._optionID);\n that.popup.open();\n that._resizeFilterInput();\n that._focusItem();\n }\n },\n\n close: function() {\n this._attachAriaActiveDescendant();\n this.popup.close();\n },\n\n _attachAriaActiveDescendant: function() {\n var wrapper = this.wrapper,\n inputId = wrapper.find(\".k-input-inner\").attr('id');\n\n wrapper.attr(\"aria-activedescendant\", inputId);\n },\n\n _focusInput: function () {\n this._focusElement(this.filterInput);\n },\n\n _resizeFilterInput: function () {\n var filterInput = this.filterInput;\n var originalPrevent = this._prevent;\n\n if (!filterInput) {\n return;\n }\n\n var isInputActive = this.filterInput[0] === activeElement();\n var caret = kendo.caret(this.filterInput[0])[0];\n\n this._prevent = true;\n\n filterInput.addClass(\"k-hidden\");\n filterInput.closest(\".k-list-filter\").css(\"width\", this.popup.element.css(\"width\"));\n filterInput.removeClass(\"k-hidden\");\n\n if (isInputActive) {\n filterInput.trigger(\"focus\");\n kendo.caret(filterInput[0], caret);\n }\n\n this._prevent = originalPrevent;\n },\n\n _allowOpening: function() {\n return this.hasOptionLabel() || this.filterInput || Select.fn._allowOpening.call(this);\n },\n\n toggle: function(toggle) {\n this._toggle(toggle, true);\n },\n\n current: function(candidate) {\n var current;\n\n if (candidate === undefined) {\n current = this.listView.focus();\n\n if (!current && this.selectedIndex === 0 && this.hasOptionLabel()) {\n return this.optionLabel;\n }\n\n return current;\n }\n\n this._focus(candidate);\n },\n\n dataItem: function(index) {\n var that = this;\n var dataItem = null;\n\n if (index === null) { return index; }\n\n if (index === undefined) {\n dataItem = that.listView.selectedDataItems()[0];\n } else {\n if (typeof index !== \"number\") {\n if (that.options.virtual) {\n return that.dataSource.getByUid($(index).data(\"uid\"));\n }\n if (index.hasClass(\"k-list-optionlabel\")) {\n index = -1;\n } else {\n index = $(that.items()).index(index);\n }\n } else if (that.hasOptionLabel()) {\n index -= 1;\n }\n\n dataItem = that.dataSource.flatView()[index];\n }\n\n if (!dataItem) {\n dataItem = that._optionLabelDataItem();\n }\n\n return dataItem;\n },\n\n refresh: function() {\n this.listView.refresh();\n },\n\n text: function (text) {\n var that = this;\n var loweredText;\n var ignoreCase = that.options.ignoreCase;\n\n text = text === null ? \"\" : text;\n\n if (text !== undefined) {\n if (typeof text !== \"string\") {\n that._textAccessor(text);\n return;\n }\n\n loweredText = ignoreCase ? text.toLowerCase() : text;\n\n that._select(function(data) {\n data = that._text(data);\n\n if (ignoreCase) {\n data = (data + \"\").toLowerCase();\n }\n\n return data === loweredText;\n }).done(function() {\n that._textAccessor(that.dataItem() || text);\n });\n\n } else {\n return that._textAccessor();\n }\n },\n\n _clearFilter: function() {\n $(this.filterInput).val(\"\");\n Select.fn._clearFilter.call(this);\n },\n\n value: function(value) {\n var that = this;\n var listView = that.listView;\n var dataSource = that.dataSource;\n var valueFn = function() { that.value(value); };\n\n if (value === undefined) {\n value = that._accessor() || that.listView.value()[0];\n return value === undefined || value === null ? \"\" : value;\n }\n\n that.requireValueMapper(that.options, value);\n\n if (value || !that.hasOptionLabel()) {\n that._initialIndex = null;\n }\n\n this.trigger(\"set\", { value: value });\n\n if (that._request && that.options.cascadeFrom && that.listView.bound()) {\n if (that._valueSetter) {\n dataSource.unbind(CHANGE, that._valueSetter);\n }\n\n that._valueSetter = valueFn.bind(that);\n\n dataSource.one(CHANGE, that._valueSetter);\n return;\n }\n\n if (that._isFilterEnabled() && listView.bound() && listView.isFiltered()) {\n that._clearFilter();\n } else {\n that._fetchData();\n }\n\n listView.value(value).done(function() {\n that._old = that._valueBeforeCascade = that._accessor();\n that._oldIndex = that.selectedIndex;\n });\n },\n\n hasOptionLabel: function() {\n return this.optionLabel && !!this.optionLabel[0];\n },\n\n _optionLabel: function() {\n var that = this;\n var options = that.options;\n var optionLabel = options.optionLabel;\n var template = options.optionLabelTemplate;\n\n if (!optionLabel) {\n that.optionLabel.off().remove();\n that.optionLabel = $();\n return;\n }\n\n if (!template) {\n template = \"#:\";\n\n if (typeof optionLabel === \"string\") {\n template += \"data\";\n } else {\n template += kendo.expr(options.dataTextField, \"data\");\n }\n\n template += \"#\";\n }\n\n if (typeof template !== \"function\") {\n template = kendo.template(template);\n }\n\n that.optionLabelTemplate = template;\n\n if (!that.hasOptionLabel()) {\n that.optionLabel = $('
').prependTo(that.list);\n }\n\n that.optionLabel.html(template(optionLabel))\n .off()\n .on(CLICKEVENTS, that._click.bind(that))\n .on(HOVEREVENTS, that._toggleHover);\n\n that.angular(\"compile\", function() {\n return { elements: that.optionLabel, data: [{ dataItem: that._optionLabelDataItem() }] };\n });\n },\n\n _optionLabelText: function() {\n var optionLabel = this.options.optionLabel;\n return (typeof optionLabel === \"string\") ? optionLabel : this._text(optionLabel);\n },\n\n _optionLabelDataItem: function() {\n var that = this;\n var optionLabel = that.options.optionLabel;\n\n if (that.hasOptionLabel()) {\n return $.isPlainObject(optionLabel) ? new ObservableObject(optionLabel) : that._assignInstance(that._optionLabelText(), \"\");\n }\n\n return undefined;\n },\n\n _buildOptions: function(data) {\n var that = this;\n if (!that._isSelect) {\n return;\n }\n\n var value = that.listView.value()[0];\n var optionLabel = that._optionLabelDataItem();\n var optionLabelValue = optionLabel && that._value(optionLabel);\n\n if (value === undefined || value === null) {\n value = \"\";\n }\n\n if (optionLabel) {\n if (optionLabelValue === undefined || optionLabelValue === null) {\n optionLabelValue = \"\";\n }\n\n optionLabel = '\";\n }\n\n that._options(data, optionLabel, value);\n\n if (value !== List.unifyType(that._accessor(), typeof value)) {\n that._customOption = null;\n that._custom(value);\n }\n },\n\n _listBound: function() {\n\n var that = this;\n var initialIndex = that._initialIndex;\n var filtered = that._state === STATE_FILTER;\n\n var data = that.dataSource.flatView();\n var dataItem;\n\n that._presetValue = false;\n\n that._renderFooter();\n that._renderNoData();\n that._toggleNoData(!data.length);\n\n that._resizePopup(true);\n\n that.popup.position();\n\n that._buildOptions(data);\n\n if (!filtered) {\n if (that._open) {\n that.toggle(that._allowOpening());\n }\n\n that._open = false;\n\n if (!that._fetch) {\n if (data.length) {\n if (!that.listView.value().length && initialIndex > -1 && initialIndex !== null) {\n that.select(initialIndex);\n }\n\n that._initialIndex = null;\n dataItem = that.listView.selectedDataItems()[0];\n if (dataItem && that.text() !== that._text(dataItem)) {\n that._selectValue(dataItem);\n }\n } else if (that._textAccessor() !== that._optionLabelText()) {\n that.listView.value(\"\");\n that._selectValue(null);\n that._oldIndex = that.selectedIndex;\n }\n }\n }\n\n that._hideBusy();\n that.trigger(\"dataBound\");\n },\n\n _listChange: function() {\n this._selectValue(this.listView.selectedDataItems()[0]);\n\n if (this._presetValue || (this._old && this._oldIndex === -1)) {\n this._oldIndex = this.selectedIndex;\n }\n },\n\n _filterPaste: function() {\n this._search();\n },\n\n _attachFocusHandlers: function() {\n var that = this;\n var wrapper = that.wrapper;\n\n wrapper.on(\"focusin\" + nsFocusEvent, that._focusinHandler.bind(that))\n .on(\"focusout\" + nsFocusEvent, that._focusoutHandler.bind(that));\n if(that.filterInput) {\n that.filterInput.on(\"focusin\" + nsFocusEvent, that._focusinHandler.bind(that))\n .on(\"focusout\" + nsFocusEvent, that._focusoutHandler.bind(that));\n }\n },\n\n _focusHandler: function() {\n this.wrapper.trigger(\"focus\");\n },\n\n _focusinHandler: function() {\n this.wrapper.addClass(FOCUSED);\n this._prevent = false;\n },\n\n _focusoutHandler: function() {\n var that = this;\n var isIFrame = window.self !== window.top;\n\n if (!that._prevent) {\n clearTimeout(that._typingTimeout);\n\n if (support.mobileOS.ios && isIFrame) {\n that._change();\n } else {\n that._blur();\n }\n\n that.wrapper.removeClass(FOCUSED);\n that._prevent = true;\n that._open = false;\n that.element.trigger(\"blur\");\n }\n },\n\n _wrapperMousedown: function() {\n this._prevent = !!this.filterInput;\n },\n\n _wrapperClick: function(e) {\n e.preventDefault();\n this.popup.unbind(\"activate\", this._focusInputHandler);\n this._focused = this.wrapper;\n this._prevent = false;\n this._toggle();\n },\n\n _editable: function(options) {\n var that = this;\n var element = that.element;\n var disable = options.disable;\n var readonly = options.readonly;\n var wrapper = that.wrapper.add(that.filterInput).off(ns);\n var dropDownWrapper = that.wrapper.off(HOVEREVENTS);\n\n if (!readonly && !disable) {\n element.prop(DISABLED, false).prop(READONLY, false);\n\n dropDownWrapper\n .removeClass(STATEDISABLED)\n .on(HOVEREVENTS, that._toggleHover);\n\n wrapper\n .attr(TABINDEX, wrapper.data(TABINDEX))\n .attr(ARIA_DISABLED, false)\n .attr(ARIA_READONLY, false)\n .on(\"keydown\" + ns, that, that._keydown.bind(that))\n .on(kendo.support.mousedown + ns, that._wrapperMousedown.bind(that))\n .on(\"paste\" + ns, that._filterPaste.bind(that));\n\n that.wrapper.on(\"click\" + ns, that._wrapperClick.bind(that));\n\n if (!that.filterInput) {\n wrapper.on(\"keypress\" + ns, that._keypress.bind(that));\n } else {\n wrapper.on(\"input\" + ns, that._search.bind(that));\n }\n\n } else if (disable) {\n wrapper.removeAttr(TABINDEX);\n dropDownWrapper.addClass(STATEDISABLED);\n } else {\n dropDownWrapper.removeClass(STATEDISABLED);\n }\n\n element.attr(DISABLED, disable)\n .attr(READONLY, readonly);\n\n wrapper.attr(ARIA_DISABLED, disable)\n .attr(ARIA_READONLY, readonly);\n },\n\n _keydown: function(e) {\n var that = this;\n var key = e.keyCode;\n var altKey = e.altKey;\n var isInputActive;\n var handled;\n\n var isPopupVisible = that.popup.visible();\n\n if (that.filterInput) {\n isInputActive = that.filterInput[0] === activeElement();\n }\n\n if (key === keys.LEFT) {\n key = keys.UP;\n handled = true;\n } else if (key === keys.RIGHT) {\n key = keys.DOWN;\n handled = true;\n }\n\n if (handled && isInputActive) {\n return;\n }\n\n e.keyCode = key;\n\n if ((altKey && key === keys.UP) || key === keys.ESC) {\n that._focusElement(that.wrapper);\n }\n\n if (that._state === STATE_FILTER && key === keys.ESC) {\n that._clearFilter();\n that._open = false;\n that._state = STATE_ACCEPT;\n }\n\n if (key === keys.ENTER && that._typingTimeout && that.filterInput && isPopupVisible) {\n e.preventDefault();\n return;\n }\n\n if (key === keys.SPACEBAR && !isInputActive) {\n that.toggle(!isPopupVisible);\n e.preventDefault();\n }\n\n handled = that._move(e);\n\n if (handled) {\n return;\n }\n\n if (!isPopupVisible || !that.filterInput) {\n var current = that._focus();\n\n if (key === keys.HOME) {\n handled = true;\n that._firstItem();\n } else if (key === keys.END) {\n handled = true;\n that._lastItem();\n }\n\n if (handled) {\n if (that.trigger(\"select\", { dataItem: that._getElementDataItem(that._focus()), item: that._focus() })) {\n that._focus(current);\n return;\n }\n\n that._select(that._focus(), true).done(function() {\n if (!isPopupVisible) {\n that._blur();\n }\n });\n e.preventDefault();\n }\n }\n\n if (!altKey && !handled && that.filterInput) {\n that._search();\n }\n },\n\n _matchText: function(text, word) {\n var ignoreCase = this.options.ignoreCase;\n\n if (text === undefined || text === null) {\n return false;\n }\n\n text = text + \"\";\n\n if (ignoreCase) {\n text = text.toLowerCase();\n }\n\n return text.indexOf(word) === 0;\n },\n\n _shuffleData: function(data, splitIndex) {\n var optionDataItem = this._optionLabelDataItem();\n\n if (optionDataItem) {\n data = [optionDataItem].concat(data);\n }\n\n return data.slice(splitIndex).concat(data.slice(0, splitIndex));\n },\n\n _selectNext: function() {\n var that = this;\n var data = that.dataSource.flatView();\n var dataLength = data.length + (that.hasOptionLabel() ? 1 : 0);\n var isInLoop = sameCharsOnly(that._word, that._last);\n var startIndex = that.selectedIndex;\n var oldFocusedItem;\n var text;\n\n if (startIndex === -1) {\n startIndex = 0;\n } else {\n startIndex += isInLoop ? 1 : 0;\n startIndex = normalizeIndex(startIndex, dataLength);\n }\n\n data = data.toJSON ? data.toJSON() : data.slice();\n data = that._shuffleData(data, startIndex);\n\n for (var idx = 0; idx < dataLength; idx++) {\n text = that._text(data[idx]);\n\n if (isInLoop && that._matchText(text, that._last)) {\n break;\n } else if (that._matchText(text, that._word)) {\n break;\n }\n }\n\n if (idx !== dataLength) {\n oldFocusedItem = that._focus();\n\n that._select(normalizeIndex(startIndex + idx, dataLength)).done(function() {\n var done = function() {\n if (!that.popup.visible()) {\n that._change();\n }\n };\n\n if (that.trigger(\"select\", { dataItem: that._getElementDataItem(that._focus()), item: that._focus() })) {\n that._select(oldFocusedItem).done(done);\n } else {\n done();\n }\n });\n }\n },\n\n _keypress: function(e) {\n var that = this;\n\n if (e.which === 0 || e.keyCode === kendo.keys.ENTER) {\n return;\n }\n\n var character = String.fromCharCode(e.charCode || e.keyCode);\n\n if (that.options.ignoreCase) {\n character = character.toLowerCase();\n }\n\n if (character === \" \") {\n e.preventDefault();\n }\n\n that._word += character;\n that._last = character;\n\n that._search();\n },\n\n _popupOpen: function() {\n var popup = this.popup;\n\n popup.wrapper = kendo.wrap(popup.element);\n\n if (popup.element.closest(\".km-root\")[0]) {\n popup.wrapper.addClass(\"km-popup km-widget\");\n this.wrapper.addClass(\"km-widget\");\n }\n },\n\n _popup: function() {\n Select.fn._popup.call(this);\n this.popup.one(\"open\", this._popupOpen.bind(this));\n },\n\n _getElementDataItem: function(element) {\n if (!element || !element[0]) {\n return null;\n }\n\n if (element[0] === this.optionLabel[0]) {\n return this._optionLabelDataItem();\n }\n\n return this.listView.dataItemByIndex(this.listView.getElementIndex(element));\n },\n\n _click: function (e) {\n var that = this;\n var item = e.item || $(e.currentTarget);\n\n e.preventDefault();\n\n if (that.trigger(\"select\", { dataItem: that._getElementDataItem(item), item: item })) {\n that.close();\n return;\n }\n\n that._userTriggered = true;\n\n that._select(item).done(function() {\n that._blur();\n that._focusElement(that.wrapper);\n });\n },\n\n _focusElement: function(element) {\n var active = activeElement();\n var wrapper = this.wrapper;\n var filterInput = this.filterInput;\n var compareElement = element === filterInput ? wrapper : filterInput;\n var touchEnabled = support.mobileOS && (support.touch || support.MSPointers || support.pointers);\n\n if (filterInput && filterInput[0] === element[0] && touchEnabled) {\n return;\n }\n\n if (filterInput && (compareElement[0] === active || this._focusFilter)) {\n this._focusFilter = false;\n this._prevent = true;\n this._focused = element.trigger(\"focus\");\n }\n },\n\n _searchByWord: function(word) {\n if (!word) {\n return;\n }\n\n var that = this;\n var ignoreCase = that.options.ignoreCase;\n\n if (ignoreCase) {\n word = word.toLowerCase();\n }\n\n that._select(function(dataItem) {\n return that._matchText(that._text(dataItem), word);\n });\n },\n\n _inputValue: function() {\n return this.text();\n },\n\n _search: function() {\n var that = this;\n var dataSource = that.dataSource;\n\n clearTimeout(that._typingTimeout);\n\n if (that._isFilterEnabled()) {\n that._typingTimeout = setTimeout(function() {\n var value = that.filterInput.val();\n\n if (that._prev !== value) {\n that._prev = value;\n that.search(value);\n that._resizeFilterInput();\n }\n\n that._typingTimeout = null;\n }, that.options.delay);\n } else {\n that._typingTimeout = setTimeout(function() {\n that._word = \"\";\n }, that.options.delay);\n\n if (!that.listView.bound()) {\n dataSource.fetch().done(function () {\n that._selectNext();\n });\n return;\n }\n\n that._selectNext();\n }\n },\n\n _get: function(candidate) {\n var data, found, idx;\n var isFunction = typeof candidate === \"function\";\n var jQueryCandidate = !isFunction ? $(candidate) : $();\n\n if (this.hasOptionLabel()) {\n if (typeof candidate === \"number\") {\n if (candidate > -1) {\n candidate -= 1;\n }\n } else if (jQueryCandidate.hasClass(\"k-list-optionlabel\")) {\n candidate = -1;\n }\n }\n\n if (isFunction) {\n data = this.dataSource.flatView();\n\n for (idx = 0; idx < data.length; idx++) {\n if (candidate(data[idx])) {\n candidate = idx;\n found = true;\n break;\n }\n }\n\n if (!found) {\n candidate = -1;\n }\n }\n\n return candidate;\n },\n\n _firstItem: function() {\n if (this.hasOptionLabel()) {\n this._focus(this.optionLabel);\n } else {\n this.listView.focusFirst();\n }\n },\n\n _lastItem: function() {\n this._resetOptionLabel();\n this.listView.focusLast();\n },\n\n _nextItem: function() {\n var focusIndex;\n\n if (this.optionLabel.hasClass(\"k-focus\")) {\n this._resetOptionLabel();\n this.listView.focusFirst();\n focusIndex = 1;\n } else {\n focusIndex = this.listView.focusNext();\n }\n\n return focusIndex;\n },\n\n _prevItem: function() {\n var focusIndex;\n\n if (this.optionLabel.hasClass(\"k-focus\")) {\n return;\n }\n\n focusIndex = this.listView.focusPrev();\n\n if (!this.listView.focus() && !this.options.virtual) {\n this._focus(this.optionLabel);\n }\n\n return focusIndex;\n },\n\n _focusItem: function() {\n var options = this.options;\n var listView = this.listView;\n var focusedItem = listView.focus();\n var index = listView.select();\n\n index = index[index.length - 1];\n\n if (index === undefined && options.highlightFirst && !focusedItem) {\n index = 0;\n }\n\n if (index !== undefined) {\n listView.focus(index);\n } else {\n if (options.optionLabel && (!options.virtual || options.virtual.mapValueTo !== \"dataItem\")) {\n this._focus(this.optionLabel);\n this._select(this.optionLabel);\n this.listView.content.scrollTop(0);\n } else {\n listView.scrollToIndex(0);\n }\n }\n },\n\n _resetOptionLabel: function(additionalClass) {\n this.optionLabel.removeClass(\"k-focus\" + (additionalClass || \"\")).removeAttr(\"id\");\n },\n\n _focus: function(candidate) {\n var listView = this.listView;\n var optionLabel = this.optionLabel;\n\n if (candidate === undefined) {\n candidate = listView.focus();\n\n if (!candidate && optionLabel.hasClass(\"k-focus\")) {\n candidate = optionLabel;\n }\n\n return candidate;\n }\n\n this._resetOptionLabel();\n\n candidate = this._get(candidate);\n\n listView.focus(candidate);\n\n if (candidate === -1) {\n optionLabel.addClass(\"k-focus\")\n .attr(\"id\", listView._optionID);\n\n this._focused.add(this.filterInput)\n .removeAttr(\"aria-activedescendant\")\n .attr(\"aria-activedescendant\", listView._optionID);\n }\n },\n\n _select: function(candidate, keepState) {\n var that = this;\n\n candidate = that._get(candidate);\n\n return that.listView.select(candidate).done(function() {\n if (!keepState && that._state === STATE_FILTER) {\n that._state = STATE_ACCEPT;\n }\n\n if (candidate === -1) {\n that._selectValue(null);\n }\n });\n },\n\n _selectValue: function(dataItem) {\n var that = this;\n var optionLabel = that.options.optionLabel;\n var idx = that.listView.select();\n\n var value = \"\";\n var text = \"\";\n\n idx = idx[idx.length - 1];\n if (idx === undefined) {\n idx = -1;\n }\n\n this._resetOptionLabel(\" k-selected\");\n\n if (dataItem || dataItem === 0) {\n text = dataItem;\n value = that._dataValue(dataItem);\n if (optionLabel) {\n idx += 1;\n }\n } else if (optionLabel) {\n that._focus(that.optionLabel.addClass(\"k-selected\"));\n\n text = that._optionLabelText();\n\n if (typeof optionLabel === \"string\") {\n value = \"\";\n } else {\n value = that._value(optionLabel);\n }\n\n idx = 0;\n }\n\n that.selectedIndex = idx;\n\n if (value === null) {\n value = \"\";\n }\n\n that._textAccessor(text);\n that._accessor(value, idx);\n\n that._triggerCascade();\n },\n\n _mobile: function() {\n var that = this,\n popup = that.popup,\n mobileOS = support.mobileOS,\n root = popup.element.parents(\".km-root\").eq(0);\n\n if (root.length && mobileOS) {\n popup.options.animation.open.effects = (mobileOS.android || mobileOS.meego) ? \"fadeIn\" : (mobileOS.ios || mobileOS.wp) ? \"slideIn:up\" : popup.options.animation.open.effects;\n }\n },\n\n _filterHeader: function() {\n var filterTemplate = '