658 lines
30 KiB
JavaScript
658 lines
30 KiB
JavaScript
/**
|
|
* Kendo UI v2016.1.226 (http://www.telerik.com/kendo-ui)
|
|
* Copyright 2016 Telerik AD. All rights reserved.
|
|
*
|
|
* Kendo UI commercial licenses may be obtained at
|
|
* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete
|
|
* If you do not own a commercial license, this file shall be governed by the trial license terms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
(function (f, define) {
|
|
define('kendo.combobox', [
|
|
'kendo.list',
|
|
'kendo.mobile.scroller'
|
|
], f);
|
|
}(function () {
|
|
var __meta__ = {
|
|
id: 'combobox',
|
|
name: 'ComboBox',
|
|
category: 'web',
|
|
description: 'The ComboBox widget allows the selection from pre-defined values or entering a new value.',
|
|
depends: ['list'],
|
|
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, Select = ui.Select, caret = kendo.caret, support = kendo.support, placeholderSupported = support.placeholder, activeElement = kendo._activeElement, keys = kendo.keys, ns = '.kendoComboBox', CLICK = 'click' + ns, MOUSEDOWN = 'mousedown' + ns, DISABLED = 'disabled', READONLY = 'readonly', CHANGE = 'change', DEFAULT = 'k-state-default', FOCUSED = 'k-state-focused', STATEDISABLED = 'k-state-disabled', ARIA_DISABLED = 'aria-disabled', ARIA_READONLY = 'aria-readonly', STATE_FILTER = 'filter', STATE_ACCEPT = 'accept', STATE_REBIND = 'rebind', HOVEREVENTS = 'mouseenter' + ns + ' mouseleave' + ns, proxy = $.proxy;
|
|
var ComboBox = Select.extend({
|
|
init: function (element, options) {
|
|
var that = this, text, disabled;
|
|
that.ns = ns;
|
|
options = $.isArray(options) ? { dataSource: options } : options;
|
|
Select.fn.init.call(that, element, options);
|
|
options = that.options;
|
|
element = that.element.on('focus' + ns, proxy(that._focusHandler, that));
|
|
options.placeholder = options.placeholder || element.attr('placeholder');
|
|
that._reset();
|
|
that._wrapper();
|
|
that._input();
|
|
that._tabindex(that.input);
|
|
that._popup();
|
|
that._dataSource();
|
|
that._ignoreCase();
|
|
that._enable();
|
|
that._oldIndex = that.selectedIndex = -1;
|
|
that._aria();
|
|
that._initialIndex = options.index;
|
|
that._initList();
|
|
that._cascade();
|
|
if (options.autoBind) {
|
|
that._filterSource();
|
|
} else {
|
|
text = options.text;
|
|
if (!text && that._isSelect) {
|
|
text = element.children(':selected').text();
|
|
}
|
|
if (text) {
|
|
that._setText(text);
|
|
}
|
|
}
|
|
if (!text) {
|
|
that._placeholder();
|
|
}
|
|
disabled = $(that.element).parents('fieldset').is(':disabled');
|
|
if (disabled) {
|
|
that.enable(false);
|
|
}
|
|
kendo.notify(that);
|
|
},
|
|
options: {
|
|
name: 'ComboBox',
|
|
enabled: true,
|
|
index: -1,
|
|
text: null,
|
|
value: null,
|
|
autoBind: true,
|
|
delay: 200,
|
|
dataTextField: '',
|
|
dataValueField: '',
|
|
minLength: 0,
|
|
height: 200,
|
|
highlightFirst: true,
|
|
filter: 'none',
|
|
placeholder: '',
|
|
suggest: false,
|
|
cascadeFrom: '',
|
|
cascadeFromField: '',
|
|
ignoreCase: true,
|
|
animation: {},
|
|
virtual: false,
|
|
template: null,
|
|
groupTemplate: '#:data#',
|
|
fixedGroupTemplate: '#:data#'
|
|
},
|
|
events: [
|
|
'open',
|
|
'close',
|
|
CHANGE,
|
|
'select',
|
|
'filtering',
|
|
'dataBinding',
|
|
'dataBound',
|
|
'cascade',
|
|
'set'
|
|
],
|
|
setOptions: function (options) {
|
|
Select.fn.setOptions.call(this, options);
|
|
this.listView.setOptions(options);
|
|
this._accessors();
|
|
this._aria();
|
|
},
|
|
destroy: function () {
|
|
var that = this;
|
|
that.input.off(ns);
|
|
that.element.off(ns);
|
|
that._inputWrapper.off(ns);
|
|
that._arrow.parent().off(CLICK + ' ' + MOUSEDOWN);
|
|
Select.fn.destroy.call(that);
|
|
},
|
|
_focusHandler: function () {
|
|
this.input.focus();
|
|
},
|
|
_arrowClick: function () {
|
|
this._toggle();
|
|
},
|
|
_inputFocus: function () {
|
|
this._inputWrapper.addClass(FOCUSED);
|
|
this._placeholder(false);
|
|
},
|
|
_inputFocusout: function () {
|
|
var that = this;
|
|
var value = that.value();
|
|
that._inputWrapper.removeClass(FOCUSED);
|
|
clearTimeout(that._typingTimeout);
|
|
that._typingTimeout = null;
|
|
that.text(that.text());
|
|
if (value !== that.value() && that.trigger('select', { item: that._focus() })) {
|
|
that.value(value);
|
|
return;
|
|
}
|
|
that._placeholder();
|
|
that._blur();
|
|
that.element.blur();
|
|
},
|
|
_editable: function (options) {
|
|
var that = this, disable = options.disable, readonly = options.readonly, wrapper = that._inputWrapper.off(ns), input = that.element.add(that.input.off(ns)), arrow = that._arrow.parent().off(CLICK + ' ' + MOUSEDOWN);
|
|
if (!readonly && !disable) {
|
|
wrapper.addClass(DEFAULT).removeClass(STATEDISABLED).on(HOVEREVENTS, that._toggleHover);
|
|
input.removeAttr(DISABLED).removeAttr(READONLY).attr(ARIA_DISABLED, false).attr(ARIA_READONLY, false);
|
|
arrow.on(CLICK, proxy(that._arrowClick, that)).on(MOUSEDOWN, function (e) {
|
|
e.preventDefault();
|
|
});
|
|
that.input.on('keydown' + ns, proxy(that._keydown, that)).on('focus' + ns, proxy(that._inputFocus, that)).on('focusout' + ns, proxy(that._inputFocusout, that));
|
|
} else {
|
|
wrapper.addClass(disable ? STATEDISABLED : DEFAULT).removeClass(disable ? DEFAULT : STATEDISABLED);
|
|
input.attr(DISABLED, disable).attr(READONLY, readonly).attr(ARIA_DISABLED, disable).attr(ARIA_READONLY, readonly);
|
|
}
|
|
},
|
|
open: function () {
|
|
var that = this;
|
|
var state = that._state;
|
|
if (that.popup.visible()) {
|
|
return;
|
|
}
|
|
if (!that.listView.bound() && state !== STATE_FILTER || state === STATE_ACCEPT) {
|
|
that._open = true;
|
|
that._state = STATE_REBIND;
|
|
that._filterSource();
|
|
} else {
|
|
that.popup.open();
|
|
that._focusItem();
|
|
}
|
|
},
|
|
_updateSelectionState: function () {
|
|
var that = this;
|
|
var text = that.options.text;
|
|
var value = that.options.value;
|
|
if (that.listView.isFiltered()) {
|
|
return;
|
|
}
|
|
if (that.selectedIndex === -1) {
|
|
if (text === undefined || text === null) {
|
|
text = value;
|
|
}
|
|
that._accessor(value);
|
|
that.input.val(text || that.input.val());
|
|
that._placeholder();
|
|
} else if (that._oldIndex === -1) {
|
|
that._oldIndex = that.selectedIndex;
|
|
}
|
|
},
|
|
_buildOptions: function (data) {
|
|
var that = this;
|
|
if (!that._isSelect) {
|
|
return;
|
|
}
|
|
var custom = that._customOption;
|
|
if (that._state === STATE_REBIND) {
|
|
that._state = '';
|
|
}
|
|
that._customOption = undefined;
|
|
that._options(data, '', that.value());
|
|
if (custom && custom[0].selected) {
|
|
that._custom(custom.val());
|
|
}
|
|
},
|
|
_updateSelection: function () {
|
|
var that = this;
|
|
var listView = that.listView;
|
|
var initialIndex = that._initialIndex;
|
|
var hasInitialIndex = initialIndex !== null && initialIndex > -1;
|
|
var filtered = that._state === STATE_FILTER;
|
|
if (filtered) {
|
|
$(listView.focus()).removeClass('k-state-selected');
|
|
return;
|
|
}
|
|
if (that._fetch) {
|
|
return;
|
|
}
|
|
if (!listView.value().length) {
|
|
if (hasInitialIndex) {
|
|
that.select(initialIndex);
|
|
} else if (that._accessor()) {
|
|
listView.value(that._accessor());
|
|
}
|
|
}
|
|
that._initialIndex = null;
|
|
var dataItem = listView.selectedDataItems()[0];
|
|
if (!dataItem) {
|
|
return;
|
|
}
|
|
if (that._value(dataItem) !== that.value()) {
|
|
that._custom(that._value(dataItem));
|
|
}
|
|
if (that.text() && that.text() !== that._text(dataItem)) {
|
|
that._selectValue(dataItem);
|
|
}
|
|
},
|
|
_updateItemFocus: function () {
|
|
var listView = this.listView;
|
|
if (!this.options.highlightFirst) {
|
|
listView.focus(-1);
|
|
} else if (!listView.focus() && !listView.focusIndex()) {
|
|
listView.focus(0);
|
|
}
|
|
},
|
|
_listBound: function () {
|
|
var that = this;
|
|
var isActive = that.input[0] === activeElement();
|
|
var data = that.dataSource.flatView();
|
|
var skip = that.listView.skip();
|
|
var isFirstPage = skip === undefined || skip === 0;
|
|
that._angularItems('compile');
|
|
that._presetValue = false;
|
|
that._resizePopup();
|
|
that.popup.position();
|
|
that._buildOptions(data);
|
|
that._makeUnselectable();
|
|
that._updateSelection();
|
|
if (data.length && isFirstPage) {
|
|
that._updateItemFocus();
|
|
if (that.options.suggest && isActive && that.input.val()) {
|
|
that.suggest(data[0]);
|
|
}
|
|
}
|
|
if (that._open) {
|
|
that._open = false;
|
|
if (that._typingTimeout && !isActive) {
|
|
that.popup.close();
|
|
} else {
|
|
that.toggle(!!data.length);
|
|
}
|
|
that._typingTimeout = null;
|
|
}
|
|
that._hideBusy();
|
|
that.trigger('dataBound');
|
|
},
|
|
_listChange: function () {
|
|
this._selectValue(this.listView.selectedDataItems()[0]);
|
|
if (this._presetValue) {
|
|
this._oldIndex = this.selectedIndex;
|
|
}
|
|
},
|
|
_get: function (candidate) {
|
|
var data, found, idx;
|
|
if (typeof candidate === 'function') {
|
|
data = this.dataSource.flatView();
|
|
for (idx = 0; idx < data.length; idx++) {
|
|
if (candidate(data[idx])) {
|
|
candidate = idx;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
candidate = -1;
|
|
}
|
|
}
|
|
return candidate;
|
|
},
|
|
_select: function (candidate, keepState) {
|
|
candidate = this._get(candidate);
|
|
if (candidate === -1) {
|
|
this.input[0].value = '';
|
|
this._accessor('');
|
|
}
|
|
this.listView.select(candidate);
|
|
if (!keepState && this._state === STATE_FILTER) {
|
|
this._state = STATE_ACCEPT;
|
|
}
|
|
},
|
|
_selectValue: function (dataItem) {
|
|
var idx = this.listView.select();
|
|
var value = '';
|
|
var text = '';
|
|
idx = idx[idx.length - 1];
|
|
if (idx === undefined) {
|
|
idx = -1;
|
|
}
|
|
this.selectedIndex = idx;
|
|
if (idx === -1) {
|
|
value = text = this.input[0].value;
|
|
this.listView.focus(-1);
|
|
} else {
|
|
if (dataItem) {
|
|
value = this._dataValue(dataItem);
|
|
text = this._text(dataItem);
|
|
}
|
|
if (value === null) {
|
|
value = '';
|
|
}
|
|
}
|
|
this._prev = this.input[0].value = text;
|
|
this._accessor(value !== undefined ? value : text, idx);
|
|
this._placeholder();
|
|
this._triggerCascade();
|
|
},
|
|
refresh: function () {
|
|
this.listView.refresh();
|
|
},
|
|
suggest: function (word) {
|
|
var that = this;
|
|
var element = that.input[0];
|
|
var value = that.text();
|
|
var caretIdx = caret(element)[0];
|
|
var key = that._last;
|
|
var idx;
|
|
if (key == keys.BACKSPACE || key == keys.DELETE) {
|
|
that._last = undefined;
|
|
return;
|
|
}
|
|
word = word || '';
|
|
if (typeof word !== 'string') {
|
|
if (word[0]) {
|
|
word = that.dataSource.view()[List.inArray(word[0], that.ul[0])];
|
|
}
|
|
word = word ? that._text(word) : '';
|
|
}
|
|
if (caretIdx <= 0) {
|
|
caretIdx = value.toLowerCase().indexOf(word.toLowerCase()) + 1;
|
|
}
|
|
if (word) {
|
|
word = word.toString();
|
|
idx = word.toLowerCase().indexOf(value.toLowerCase());
|
|
if (idx > -1) {
|
|
value += word.substring(idx + value.length);
|
|
}
|
|
} else {
|
|
value = value.substring(0, caretIdx);
|
|
}
|
|
if (value.length !== caretIdx || !word) {
|
|
element.value = value;
|
|
if (element === activeElement()) {
|
|
caret(element, caretIdx, value.length);
|
|
}
|
|
}
|
|
},
|
|
text: function (text) {
|
|
text = text === null ? '' : text;
|
|
var that = this;
|
|
var input = that.input[0];
|
|
var ignoreCase = that.options.ignoreCase;
|
|
var loweredText = text;
|
|
var dataItem;
|
|
var value;
|
|
if (text === undefined) {
|
|
return input.value;
|
|
}
|
|
if (that.options.autoBind === false && !that.listView.bound()) {
|
|
that._setText(text);
|
|
return;
|
|
}
|
|
dataItem = that.dataItem();
|
|
if (dataItem && that._text(dataItem) === text) {
|
|
value = that._value(dataItem);
|
|
if (value === List.unifyType(that._old, typeof value)) {
|
|
that._triggerCascade();
|
|
return;
|
|
}
|
|
}
|
|
if (ignoreCase) {
|
|
loweredText = loweredText.toLowerCase();
|
|
}
|
|
that._select(function (data) {
|
|
data = that._text(data);
|
|
if (ignoreCase) {
|
|
data = (data + '').toLowerCase();
|
|
}
|
|
return data === loweredText;
|
|
});
|
|
if (that.selectedIndex < 0) {
|
|
that._accessor(text);
|
|
input.value = text;
|
|
that._triggerCascade();
|
|
}
|
|
that._prev = input.value;
|
|
},
|
|
toggle: function (toggle) {
|
|
this._toggle(toggle, true);
|
|
},
|
|
value: function (value) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var listView = that.listView;
|
|
if (value === undefined) {
|
|
value = that._accessor() || that.listView.value()[0];
|
|
return value === undefined || value === null ? '' : value;
|
|
}
|
|
that.trigger('set', { value: value });
|
|
if (value === options.value && that.input.val() === options.text) {
|
|
return;
|
|
}
|
|
that._accessor(value);
|
|
if (that._isFilterEnabled() && listView.bound() && listView.isFiltered()) {
|
|
listView.bound(false);
|
|
that._filterSource();
|
|
} else {
|
|
that._fetchData();
|
|
}
|
|
listView.value(value).done(function () {
|
|
if (that.selectedIndex === -1) {
|
|
that._accessor(value);
|
|
that.input.val(value);
|
|
that._placeholder(true);
|
|
}
|
|
that._old = that._accessor();
|
|
that._oldIndex = that.selectedIndex;
|
|
that._prev = that.input.val();
|
|
if (that._state === STATE_FILTER) {
|
|
that._state = STATE_ACCEPT;
|
|
}
|
|
});
|
|
},
|
|
_click: function (e) {
|
|
var item = e.item;
|
|
e.preventDefault();
|
|
if (this.trigger('select', { item: item })) {
|
|
this.close();
|
|
return;
|
|
}
|
|
this._userTriggered = true;
|
|
this._select(item);
|
|
this._blur();
|
|
},
|
|
_filter: function (word) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var dataSource = that.dataSource;
|
|
var ignoreCase = options.ignoreCase;
|
|
var predicate = function (dataItem) {
|
|
var text = that._text(dataItem);
|
|
if (text !== undefined) {
|
|
text = text + '';
|
|
if (text !== '' && word === '') {
|
|
return false;
|
|
}
|
|
if (ignoreCase) {
|
|
text = text.toLowerCase();
|
|
}
|
|
return text.indexOf(word) === 0;
|
|
}
|
|
};
|
|
if (ignoreCase) {
|
|
word = word.toLowerCase();
|
|
}
|
|
if (!that.ul[0].firstChild) {
|
|
dataSource.one(CHANGE, function () {
|
|
if (dataSource.view()[0]) {
|
|
that.search(word);
|
|
}
|
|
}).fetch();
|
|
return;
|
|
}
|
|
this.listView.focus(this._get(predicate));
|
|
var current = this.listView.focus();
|
|
if (current) {
|
|
if (options.suggest) {
|
|
that.suggest(current);
|
|
}
|
|
this.open();
|
|
}
|
|
if (this.options.highlightFirst && !word) {
|
|
this.listView.focusFirst();
|
|
}
|
|
},
|
|
_input: function () {
|
|
var that = this, element = that.element.removeClass('k-input')[0], accessKey = element.accessKey, wrapper = that.wrapper, SELECTOR = 'input.k-input', name = element.name || '', input;
|
|
if (name) {
|
|
name = 'name="' + name + '_input" ';
|
|
}
|
|
input = wrapper.find(SELECTOR);
|
|
if (!input[0]) {
|
|
wrapper.append('<span tabindex="-1" unselectable="on" class="k-dropdown-wrap k-state-default"><input ' + name + 'class="k-input" type="text" autocomplete="off"/><span tabindex="-1" unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s">select</span></span></span>').append(that.element);
|
|
input = wrapper.find(SELECTOR);
|
|
}
|
|
input[0].style.cssText = element.style.cssText;
|
|
input[0].title = element.title;
|
|
if (element.maxLength > -1) {
|
|
input[0].maxLength = element.maxLength;
|
|
}
|
|
input.addClass(element.className).val(this.options.text || element.value).css({
|
|
width: '100%',
|
|
height: element.style.height
|
|
}).attr({
|
|
'role': 'combobox',
|
|
'aria-expanded': false
|
|
}).show();
|
|
if (placeholderSupported) {
|
|
input.attr('placeholder', that.options.placeholder);
|
|
}
|
|
if (accessKey) {
|
|
element.accessKey = '';
|
|
input[0].accessKey = accessKey;
|
|
}
|
|
that._focused = that.input = input;
|
|
that._inputWrapper = $(wrapper[0].firstChild);
|
|
that._arrow = wrapper.find('.k-icon').attr({
|
|
'role': 'button',
|
|
'tabIndex': -1
|
|
});
|
|
if (element.id) {
|
|
that._arrow.attr('aria-controls', that.ul[0].id);
|
|
}
|
|
},
|
|
_keydown: function (e) {
|
|
var that = this, key = e.keyCode;
|
|
that._last = key;
|
|
clearTimeout(that._typingTimeout);
|
|
that._typingTimeout = null;
|
|
if (key != keys.TAB && !that._move(e)) {
|
|
that._search();
|
|
}
|
|
},
|
|
_placeholder: function (show) {
|
|
if (placeholderSupported) {
|
|
return;
|
|
}
|
|
var that = this, input = that.input, placeholder = that.options.placeholder, value;
|
|
if (placeholder) {
|
|
value = that.value();
|
|
if (show === undefined) {
|
|
show = !value;
|
|
}
|
|
input.toggleClass('k-readonly', show);
|
|
if (!show) {
|
|
if (!value) {
|
|
placeholder = '';
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
input.val(placeholder);
|
|
if (!placeholder && input[0] === activeElement()) {
|
|
caret(input[0], 0, 0);
|
|
}
|
|
}
|
|
},
|
|
_search: function () {
|
|
var that = this;
|
|
that._typingTimeout = setTimeout(function () {
|
|
var value = that.text();
|
|
if (that._prev !== value) {
|
|
that._prev = value;
|
|
if (that.options.filter === 'none') {
|
|
that.listView.select(-1);
|
|
}
|
|
that.search(value);
|
|
}
|
|
that._typingTimeout = null;
|
|
}, that.options.delay);
|
|
},
|
|
_setText: function (text) {
|
|
this.input.val(text);
|
|
this._prev = text;
|
|
},
|
|
_wrapper: function () {
|
|
var that = this, element = that.element, wrapper = element.parent();
|
|
if (!wrapper.is('span.k-widget')) {
|
|
wrapper = element.hide().wrap('<span />').parent();
|
|
wrapper[0].style.cssText = element[0].style.cssText;
|
|
}
|
|
that.wrapper = wrapper.addClass('k-widget k-combobox k-header').addClass(element[0].className).css('display', '');
|
|
},
|
|
_clearSelection: function (parent, isFiltered) {
|
|
var that = this;
|
|
var hasValue = parent.value();
|
|
var custom = hasValue && parent.selectedIndex === -1;
|
|
if (this.selectedIndex == -1 && this.value()) {
|
|
return;
|
|
}
|
|
if (isFiltered || !hasValue || custom) {
|
|
that.options.value = '';
|
|
that.value('');
|
|
}
|
|
},
|
|
_preselect: function (value, text) {
|
|
this.input.val(text);
|
|
this._accessor(value);
|
|
this._old = this._accessor();
|
|
this._oldIndex = this.selectedIndex;
|
|
this.listView.setValue(value);
|
|
this._placeholder();
|
|
this._initialIndex = null;
|
|
this._presetValue = true;
|
|
}
|
|
});
|
|
ui.plugin(ComboBox);
|
|
}(window.kendo.jQuery));
|
|
return window.kendo;
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
})); |