@progress/kendo-angular-dropdowns
Version:
Dropdowns Package for Angular 2
1,025 lines (1,024 loc) • 43.6 kB
JavaScript
"use strict";
/* tslint:disable:no-null-keyword */
/* tslint:disable:max-line-length */
/* tslint:disable:no-bitwise */
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var forms_1 = require("@angular/forms");
var searchbar_component_1 = require("./searchbar.component");
var item_template_directive_1 = require("./templates/item-template.directive");
var header_template_directive_1 = require("./templates/header-template.directive");
var footer_template_directive_1 = require("./templates/footer-template.directive");
var no_data_template_directive_1 = require("./templates/no-data-template.directive");
var selection_service_1 = require("./selection.service");
var navigation_service_1 = require("./navigation.service");
var Observable_1 = require("rxjs/Observable");
require("rxjs/add/operator/filter");
require("rxjs/add/operator/catch");
require("rxjs/add/operator/do");
require("rxjs/add/operator/merge");
require("rxjs/add/operator/map");
require("rxjs/add/operator/let");
require("rxjs/add/operator/partition");
require("rxjs/add/operator/throttleTime");
require("rxjs/add/operator/distinctUntilChanged");
var Subject_1 = require("rxjs/Subject");
var Subscription_1 = require("rxjs/Subscription");
var util_1 = require("./util");
var navigation_action_1 = require("./navigation-action");
var keys_1 = require("./common/keys");
var preventable_event_1 = require("./common/preventable-event");
var kendo_angular_l10n_1 = require("@progress/kendo-angular-l10n");
var kendo_angular_popup_1 = require("@progress/kendo-angular-popup");
var InternalState;
(function (InternalState) {
InternalState[InternalState["None"] = 0] = "None";
InternalState[InternalState["SetInitial"] = 1] = "SetInitial";
InternalState[InternalState["UseInitial"] = 2] = "UseInitial";
InternalState[InternalState["UseExisting"] = 4] = "UseExisting";
InternalState[InternalState["UseCustom"] = 8] = "UseCustom";
InternalState[InternalState["UseFilter"] = 16] = "UseFilter";
InternalState[InternalState["UseNone"] = 32] = "UseNone";
InternalState[InternalState["UseEmpty"] = 64] = "UseEmpty";
})(InternalState || (InternalState = {}));
/**
* @hidden
*/
exports.COMBOBOX_VALUE_ACCESSOR = {
multi: true,
provide: forms_1.NG_VALUE_ACCESSOR,
// tslint:disable-next-line:no-use-before-declare
useExisting: core_1.forwardRef(function () { return ComboBoxComponent; })
};
/**
* Represents the Kendo UI ComboBox component for Angular.
*
* @example
* ```ts
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-combobox [data]="listItems">
* </kendo-combobox>
* `
* })
* class AppComponent {
* public listItems: Array<string> = ["Item 1", "Item 2", "Item 3", "Item 4"];
* }
* ```
*/
var ComboBoxComponent = (function () {
function ComboBoxComponent(rtl, popupService, selectionService, navigationService, cdr, wrapper) {
this.popupService = popupService;
this.selectionService = selectionService;
this.navigationService = navigationService;
this.cdr = cdr;
this.selected = [];
/**
* Specifies whether the ComboBox allows user-defined values that are not present in the dataset.
* The default value is `false`.
*
* For more information, refer to the article on [custom values]({% slug custom_values_combobox_kendouiforangular %}).
*/
this.allowCustom = false;
/**
* A user-defined callback which returns normalized custom values. Typically used when the data items are different from type `string`.
* @param { Any } value - The custom value defined by the user.
* @returns { Any }
*
* @example
* ```ts
* _@Component({
* selector: 'my-app',
* template: `
* <kendo-combobox
* [allowCustom]="true"
* [data]="listItems"
* [textField]="'text'"
* [valueField]="'value'"
* [valueNormalizer]="valueNormalizer"
* (valueChange)="onValueChange($event)"
* >
* </kendo-combobox>
* `
* })
*
* class AppComponent {
* public listItems: Array<{ text: string, value: number }> = [
* { text: "Small", value: 1 },
* { text: "Medium", value: 2 },
* { text: "Large", value: 3 }
* ];
*
* public onValueChange(value) {
* console.log("valueChange : ", value);
* }
*
* public valueNormalizer = (text: Observable<string>) => text.map((text: string) => {
* return { ProductID: null, ProductName: text };
* });
*
* }
* ```
*/
this.valueNormalizer = function (text) { return text.map(function (userInput) { return userInput; }); };
/**
* The hint displayed when the component is empty.
*
*/
this.placeholder = "";
/**
* @hidden
*
* Enables the auto-completion of the text based on the first data item.
*/
this.suggest = false;
/**
* If set to `true`, renders a button on hovering over the component. Clicking this button resets the value of the component to `undefined` and triggers the `change` event.
*/
this.clearButton = true;
/**
* Sets the disabled state of the component.
*/
this.disabled = false;
/**
* Specifies the [`tabIndex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
*/
this.tabIndex = 0;
/**
* Enables the filtering functionality. If set to `true`, the component emits the `filterChange` event.
*/
this.filterable = false;
/**
* Fires each time the value is changed.
*
* For more details, refer to the example on [events]({% slug overview_combobox_kendouiforangular %}#toc-events).
*/
this.valueChange = new core_1.EventEmitter();
/**
* Fires each time an item selection is changed.
*
* For more details, refer to the example on [events]({% slug overview_combobox_kendouiforangular %}#toc-events).
*/
this.selectionChange = new core_1.EventEmitter();
/**
* Fires each time the user types in the input.
* You can filter the source based on the passed filtration value.
*
* For more details, refer to the example on [events]({% slug overview_combobox_kendouiforangular %}#toc-events).
*/
this.filterChange = new core_1.EventEmitter();
/**
* Fires each time the popup is about to open.
* This event is preventable. If you cancel it, the popup will remain closed.
*/
this.open = new core_1.EventEmitter();
/**
* Fires each time the popup is about to close.
* This event is preventable. If you cancel it, the popup will remain open.
*/
this.close = new core_1.EventEmitter();
/**
* Fires each time the user focuses the ComboBox.
*/
this.onFocus = new core_1.EventEmitter(); //tslint:disable-line:no-output-rename
/**
* Fires each time the ComboBox gets blurred.
*/
this.onBlur = new core_1.EventEmitter(); //tslint:disable-line:no-output-rename
this.isFocused = false;
this.listBoxId = util_1.guid();
this.optionPrefix = util_1.guid();
this.onChangeCallback = function (_) { };
this.onTouchedCallback = function (_) { };
this.observableSubscriptions = new Subscription_1.Subscription();
this._state = InternalState.SetInitial;
this._filtering = false;
this._text = "";
this._open = false;
this._previousValue = undefined;
this.suggestedText = undefined;
this._popupSettings = { height: 200, animate: true };
this.popupMouseDownHandler = function (event) { return event.preventDefault(); };
this.customValueSubject = new Subject_1.Subject();
this.valueSubject = new Subject_1.Subject();
this.selectionSubject = new Subject_1.Subject();
this.direction = rtl ? 'rtl' : 'ltr';
this.wrapper = wrapper.nativeElement;
this.data = [];
this.subscribeEvents();
}
Object.defineProperty(ComboBoxComponent.prototype, "width", {
get: function () {
var wrapperOffsetWidth = 0;
if (util_1.isDocumentAvailable()) {
wrapperOffsetWidth = this.wrapper.offsetWidth;
}
var width = this.popupSettings.width || wrapperOffsetWidth;
var minWidth = isNaN(wrapperOffsetWidth) ? wrapperOffsetWidth : wrapperOffsetWidth + "px";
var maxWidth = isNaN(width) ? width : width + "px";
return { min: minWidth, max: maxWidth };
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "height", {
get: function () {
return this.popupSettings.height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "text", {
get: function () {
return this._text;
},
set: function (text) {
var textCandidate = util_1.getter(text, this.textField, true);
this._text = util_1.isPresent(textCandidate) ? textCandidate.toString() : "";
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "popupOpen", {
get: function () {
return this._open;
},
set: function (open) {
if (this.disabled || this.popupOpen === open) {
return;
}
var eventArgs = new preventable_event_1.PreventableEvent();
if (open) {
this.open.emit(eventArgs);
}
else {
this.close.emit(eventArgs);
}
if (eventArgs.isDefaultPrevented()) {
return;
}
this._toggle(open);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "activeDescendant", {
get: function () {
return this.optionPrefix + "-" + util_1.getter(this.value, this.valueField);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "appendTo", {
get: function () {
var appendTo = this.popupSettings.appendTo;
if (!appendTo || appendTo === 'root') {
return undefined;
}
return appendTo === 'component' ? this.container : appendTo;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "data", {
get: function () {
return this._data;
},
/**
* Sets the data of the ComboBox.
*
* > The data has to be provided in an array-like list.
*/
set: function (data) {
this._data = data || [];
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "value", {
get: function () {
return this._value;
},
/**
* Sets the value of the ComboBox. It can either be of the primitive (string, numbers) or of the complex (objects) type. To define the type, use the `valuePrimitive` option.
*
* > All selected values which are not present in the dataset are considered custom values. When the `Enter` key is pressed or the component loses focus, custom values get dismissed unless `allowCustom` is set to `true`.
*/
set: function (newValue) {
this.verifySettings(newValue);
this._value = newValue;
this.cdr.markForCheck();
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "popupSettings", {
get: function () {
return this._popupSettings;
},
/**
* Configures the popup of the ComboBox.
*
* The available options are:
* - `animate: Boolean`—Controls the popup animation. By default, the open and close animations are enabled.
* - `width: Number | String`—Sets the width of the popup container. By default, the width of the host element is used If set to `auto`, the component automatically adjusts the width of the popup, so no item labels are wrapped.
* - `height: Number`—Sets the height of the popup container. By default, the height is 200px.
* - `popupClass: String`—Specifies a list of CSS classes that are used to style the popup.
*/
set: function (settings) {
this._popupSettings = Object.assign({ height: 200, animate: true }, settings);
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "widgetClasses", {
get: function () {
return true;
},
enumerable: true,
configurable: true
});
/**
* @hidden
*/
ComboBoxComponent.prototype.wrapperClasses = function () {
return {
'k-dropdown-wrap': true,
'k-state-default': !this.disabled,
'k-state-disabled': this.disabled,
'k-state-focused': this.isFocused
};
};
Object.defineProperty(ComboBoxComponent.prototype, "clearable", {
get: function () {
return this.clearButton;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "widgetHeight", {
get: function () {
return this.popupSettings.height + "px";
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComboBoxComponent.prototype, "dir", {
get: function () {
return this.direction;
},
enumerable: true,
configurable: true
});
ComboBoxComponent.prototype.ngOnInit = function () {
this.createSelectionStream();
this.createValueStream();
};
ComboBoxComponent.prototype.createSelectionStream = function () {
var _this = this;
if (this.selectionSubscription) {
this.selectionSubscription.unsubscribe();
}
this.selectionSubscription = this.selectionSubject
.map(function (index) {
return {
dataItem: _this.data[index],
value: util_1.getter(_this.data[index], _this.valueField)
};
})
.distinctUntilChanged(function (prev, next) {
return prev.value === next.value;
})
.subscribe(function (args) {
_this.selectionChange.emit(args.dataItem);
});
};
ComboBoxComponent.prototype.createValueStream = function () {
var _this = this;
var valueStream = this.valueSubject
.filter(function (candidate) {
var current = _this.valuePrimitive ? _this.value : util_1.getter(_this.value, _this.valueField);
var newValue = util_1.getter(candidate, _this.valueField);
var newText = util_1.getter(candidate, _this.textField);
if (util_1.isPresent(newText)) {
newText = newText.toString();
}
if (current === newValue && _this.text === newText) {
return false;
}
else {
return true;
}
})
.map(function (candidate) {
var newValue = util_1.getter(candidate, _this.valueField);
var newText = util_1.getter(candidate, _this.textField);
return {
dataItem: candidate,
text: newText,
value: _this.valuePrimitive ? newValue : candidate
};
});
var customValueStreams = this.customValueSubject.throttleTime(300).partition(function () { return _this.allowCustom; });
var allowCustomValueStream = customValueStreams[0]
.do(function () {
_this.loading = true;
_this.disabled = true;
})
.filter(function () {
var hasChange = _this.text !== util_1.getter(_this.value, _this.textField);
_this.loading = hasChange;
_this.disabled = hasChange;
return hasChange;
})
.let(this.valueNormalizer)
.map(function (normalizedValue) {
return {
dataItem: undefined,
text: _this.text,
value: normalizedValue
};
});
var disableCustomValueStream = customValueStreams[1]
.map(function () {
return {
dataItem: undefined,
text: undefined,
value: undefined
};
});
if (this.valueSubscription) {
this.valueSubscription.unsubscribe();
}
var merged = valueStream.merge(allowCustomValueStream, disableCustomValueStream);
this.valueSubscription = merged
.catch(function () {
_this.dataItem = undefined;
_this.value = undefined;
_this.text = undefined;
_this.loading = false;
_this.disabled = false;
_this.emitChange();
return merged;
})
.subscribe(function (state) {
_this.dataItem = state.dataItem;
_this.value = state.value;
_this.text = state.text;
_this.loading = false;
_this.disabled = false;
if (_this.filterable && !util_1.isPresent(state.value) && !util_1.isPresent(state.text) && !util_1.isPresent(_this._previousValue)) {
_this.filterChange.emit("");
}
_this.emitChange();
});
};
ComboBoxComponent.prototype.subscribeEvents = function () {
var _this = this;
if (!util_1.isDocumentAvailable()) {
return;
}
[
this.selectionService.onChange
.filter(function (event) { return util_1.isPresent(event.indices[0]); })
.map(function (event) { return event.indices[0]; })
.subscribe(this.handleItemChange.bind(this)),
this.selectionService.onSelect
.filter(function (event) { return util_1.isPresent(event.indices[0]); })
.map(function (event) { return event.indices[0]; })
.subscribe(this.handleItemSelect.bind(this)),
Observable_1.Observable.merge(this.navigationService.up, this.navigationService.down, this.navigationService.home, this.navigationService.end).subscribe(function (event) { return _this.navigate(event.index); }),
this.navigationService.open.subscribe(function () { return _this.popupOpen = true; }),
this.navigationService.close.subscribe(function () { return _this.popupOpen = false; }),
this.navigationService.enter.subscribe(this.handleEnter.bind(this)),
this.navigationService.esc.subscribe(this.handleBlur.bind(this))
].forEach(function (s) { return _this.observableSubscriptions.add(s); });
};
ComboBoxComponent.prototype.unsubscribeEvents = function () {
if (!util_1.isDocumentAvailable()) {
return;
}
this.observableSubscriptions.unsubscribe();
if (this.valueSubscription) {
this.valueSubscription.unsubscribe();
}
if (this.selectionSubscription) {
this.selectionSubscription.unsubscribe();
}
};
ComboBoxComponent.prototype.handleItemChange = function (index) {
this._filtering = false;
this.change(this.data[index]);
};
ComboBoxComponent.prototype.handleItemSelect = function (index) {
this._filtering = false;
if (!this.popupOpen) {
this.change(this.data[index]);
}
else {
this.selectionSubject.next(index);
}
};
ComboBoxComponent.prototype.ngOnDestroy = function () {
this._toggle(false);
this.unsubscribeEvents();
};
ComboBoxComponent.prototype.ngOnChanges = function (changes) {
var isInitial = Boolean(changes.value && changes.value.firstChange || (util_1.isChanged("value", changes) && (this._state & InternalState.SetInitial)));
if (isInitial) {
this._state |= InternalState.UseInitial;
}
if (util_1.isChanged("valueNormalizer", changes)) {
this.createSelectionStream();
this.createValueStream();
}
if (this.valuePrimitive === undefined) {
this.valuePrimitive = this.valueField ? false : true;
}
var STATE_PROPS = /(data|value|textField|valueField|valuePrimitive)/g;
if (STATE_PROPS.test(Object.keys(changes).join())) {
this.setState(this.value);
}
var wasFiltered = util_1.isChanged("data", changes) && this._filtering;
if (wasFiltered) {
if (this.text.length > 0) {
this.search(this.text);
if (this.selectionService.focused === -1) {
this.selectionService.focused = 0;
}
}
else {
this.selectionService.focused = -1;
}
}
if (this.suggest && this.data && this.data.length && this.text) {
this.suggestedText = util_1.getter(this.data[0], this.textField);
}
};
/**
* Focuses the ComboBox.
*/
ComboBoxComponent.prototype.focus = function () {
if (!this.disabled) {
this.searchbar.focus();
}
};
/**
* Blurs the ComboBox.
*/
ComboBoxComponent.prototype.blur = function () {
if (!this.disabled) {
this.searchbar.blur();
}
};
/**
* Toggles the visibility of the popup. If you use the `toggle` method to open or close the popup,
* the `open` and `close` events will not be fired.
*
* @param open - The state of the popup.
*/
ComboBoxComponent.prototype.toggle = function (open) {
var _this = this;
Promise.resolve(null).then(function () {
_this._toggle((open === undefined) ? !_this._open : open);
_this.cdr.markForCheck();
});
};
Object.defineProperty(ComboBoxComponent.prototype, "isOpen", {
/**
* Returns the current open state of the popup.
*/
get: function () {
return this.popupOpen;
},
enumerable: true,
configurable: true
});
/**
* Resets the value of the ComboBox.
*/
ComboBoxComponent.prototype.reset = function () {
this.setState(undefined);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.clearValue = function (event) {
event.stopImmediatePropagation();
this._filtering = true;
this._previousValue = undefined;
this.change(undefined);
this.selectionService.resetSelection([]);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.writeValue = function (value) {
var isInitial = Boolean(value !== null && this._state & InternalState.SetInitial);
if (isInitial) {
this._state |= InternalState.UseInitial;
}
this.text = "";
this.setState(value);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.registerOnChange = function (fn) {
this.onChangeCallback = fn;
};
/**
* @hidden
*/
ComboBoxComponent.prototype.registerOnTouched = function (fn) {
this.onTouchedCallback = fn;
};
/**
* @hidden
*/
ComboBoxComponent.prototype.setDisabledState = function (isDisabled) {
this.disabled = isDisabled;
};
/**
* @hidden
*/
ComboBoxComponent.prototype.popupOpened = function () {
this.popupWidth = this.width.max;
this.popupMinWidth = this.width.min;
};
Object.defineProperty(ComboBoxComponent.prototype, "buttonClasses", {
/**
* @hidden
*/
get: function () {
return _a = {},
_a[this.iconClass] = !this.loading && this.iconClass,
_a['k-i-arrow-s'] = !this.loading && !this.iconClass,
_a['k-i-loading'] = this.loading,
_a['k-icon'] = true,
_a;
var _a;
},
enumerable: true,
configurable: true
});
/**
* @hidden
*/
ComboBoxComponent.prototype.onResize = function () {
if (this._open) {
var popupWrapper = this.popupRef.popupElement;
var _a = this.width, min = _a.min, max = _a.max;
popupWrapper.style.minWidth = min;
popupWrapper.style.width = max;
}
};
ComboBoxComponent.prototype.verifySettings = function (newValue) {
var valueOrText = !util_1.isPresent(this.valueField) !== !util_1.isPresent(this.textField);
if (!core_1.isDevMode()) {
return;
}
if (this.valuePrimitive === true && util_1.isPresent(newValue) && typeof newValue === "object") {
throw new Error("Expected initial value of primitive type. See http://www.telerik.com/kendo-angular-ui/components/dropdowns/combobox/#toc-value-selection");
}
if (this.valuePrimitive === false && util_1.isPresent(newValue) && typeof newValue !== "object") {
throw new Error("Expected initial value of type Object. See http://www.telerik.com/kendo-angular-ui/components/dropdowns/combobox/#toc-value-selection");
}
if (valueOrText) {
throw new Error("Expected textField and valueField options to be set. See http://www.telerik.com/kendo-angular-ui/components/dropdowns/combobox/#toc-bind-to-arrays-of-complex-data");
}
};
ComboBoxComponent.prototype.resolveState = function (value) {
var primitiveValue = util_1.getter(value, this.valueField, true);
var existing;
var state;
if (this._filtering) {
state = InternalState.UseFilter;
}
else {
state = this.data.length ? InternalState.UseExisting : (this.allowCustom ? InternalState.UseCustom : InternalState.UseNone);
}
if (state === InternalState.UseExisting) {
existing = util_1.resolveValue({ data: this.data, value: primitiveValue, valueField: this.valueField });
if (existing.dataItem !== undefined) {
state = InternalState.UseExisting;
}
else {
state = this.allowCustom ? InternalState.UseCustom : InternalState.UseEmpty;
}
}
state |= this._state & InternalState.SetInitial | this._state & InternalState.UseInitial;
this._state = state;
return existing;
};
ComboBoxComponent.prototype.setState = function (value) {
var resolved = this.resolveState(value);
var newState = { value: undefined, text: undefined, dataItem: undefined, selected: [-1] };
if (this._state & InternalState.UseFilter) {
return;
}
else if (this._state & InternalState.UseNone) {
newState.value = value;
}
else if (this._state & InternalState.UseEmpty) {
newState.selected = undefined;
newState.value = undefined;
newState.text = undefined;
newState.dataItem = undefined;
}
else if (this._state & InternalState.UseExisting) {
newState.value = value;
newState.text = resolved.dataItem;
newState.dataItem = resolved.dataItem;
newState.selected = resolved.selected;
}
else if (this._state & InternalState.UseCustom) {
newState.value = value;
newState.text = value;
newState.dataItem = value;
}
if (this._state & InternalState.UseInitial) {
this._state &= ~InternalState.UseInitial | ~InternalState.SetInitial;
this._previousValue = newState.dataItem;
}
else {
this._previousValue = this.dataItem;
}
this.text = newState.text;
this.value = this.valuePrimitive ? util_1.getter(newState.value, this.valueField, true) : newState.value;
this.dataItem = newState.dataItem;
this.selectionService.resetSelection(newState.selected);
};
ComboBoxComponent.prototype.search = function (text) {
var _this = this;
var index = this.data.findIndex(function (item) {
var itemText = util_1.getter(item, _this.textField);
itemText = itemText === undefined ? "" : itemText.toString().toLowerCase();
return itemText.startsWith(text.toLowerCase());
});
this.selectionService.focused = index;
this.suggestedText = util_1.getter(this.data[index], this.textField);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.getSuggestion = function () {
var hasSelected = !!this.selectionService.selected.length;
var shouldSuggest = this.suggest && !this.backspacePressed && this.suggestedText && this.text;
if (!hasSelected && shouldSuggest && this.suggestedText.toLowerCase().startsWith(this.text.toLowerCase())) {
return this.suggestedText;
}
else {
this.suggestedText = undefined;
}
};
ComboBoxComponent.prototype.navigate = function (index) {
if (this.data.length === 0) {
return;
}
this.text = this.data[index];
this.selectionService.select(index);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.handleNavigate = function (event) {
var hasSelected = util_1.isPresent(this.selectionService.selected[0]);
var focused = isNaN(this.selectionService.focused) ? 0 : this.selectionService.focused;
var offset = 0;
if (this.disabled) {
return;
}
if (event.keyCode === keys_1.Keys.home || event.keyCode === keys_1.Keys.end) {
return;
}
if (!hasSelected) {
if (event.keyCode === keys_1.Keys.down) {
offset = -1;
}
else if (event.keyCode === keys_1.Keys.up) {
offset = 1;
}
}
var current = offset + focused;
if (current < -1) {
current = -1;
}
var action = this.navigationService.process({
current: current,
max: this.data.length - 1,
min: 0,
originalEvent: event
});
if (action !== navigation_action_1.NavigationAction.Undefined &&
action !== navigation_action_1.NavigationAction.Left &&
action !== navigation_action_1.NavigationAction.Right &&
action !== navigation_action_1.NavigationAction.Backspace &&
action !== navigation_action_1.NavigationAction.Delete &&
((action === navigation_action_1.NavigationAction.Enter && this.popupOpen) || action !== navigation_action_1.NavigationAction.Enter)) {
event.preventDefault();
}
};
ComboBoxComponent.prototype.handleEnter = function (event) {
var focused = this.selectionService.focused;
var previousText = util_1.getter(this._previousValue, this.textField) || "";
var hasChange = this.text !== previousText;
var isCustom = false;
this._filtering = false;
if (this.allowCustom) {
isCustom = this.text !== util_1.getter(this.data[focused], this.textField);
}
else {
isCustom = focused === -1 || focused === undefined;
}
if (this.popupOpen) {
event.originalEvent.preventDefault();
}
if (!isCustom && this.popupOpen) {
this.selectionService.select(focused);
this.change(this.data[focused] || this.text, isCustom);
return;
}
if (hasChange) {
this.change(this.text, isCustom);
}
else {
this.popupOpen = false;
}
};
/**
* @hidden
*/
ComboBoxComponent.prototype.handleBlur = function () {
this._filtering = false;
var currentText = this.searchbar.value; // The value is updated, but the Angular `change` event is not emitted yet and `this.text` is not updated. Fails on suggested text.
if (!currentText && !util_1.isPresent(this._previousValue)) {
this.popupOpen = false;
this.isFocused = false;
this.onBlur.emit();
this.onTouchedCallback();
return;
}
var focused = this.selectionService.focused;
var itemText;
if (focused !== -1 && focused !== undefined) {
itemText = util_1.getter(this.data[focused], this.textField);
itemText = itemText === undefined ? "" : itemText.toString().toLowerCase();
}
if (itemText === currentText.toLowerCase()) {
this.selectionService.change(focused);
}
else {
this.change(currentText, true);
}
this.popupOpen = false;
this.isFocused = false;
this.onBlur.emit();
this.onTouchedCallback();
};
/**
* @hidden
*/
ComboBoxComponent.prototype.searchBarChange = function (text) {
var currentTextLength = this.text ? this.text.length : 0;
this.backspacePressed = (text.length < currentTextLength) ? true : false;
this.text = text;
// Reset the selection prior to filter. If a match is present, it will be resolved. If a match is not present, it is not needed.
this.selectionService.resetSelection([]);
this.popupOpen = true;
if (this.filterable) {
this._filtering = true;
this.filterChange.emit(text);
}
else {
this.search(text);
}
};
/**
* @hidden
*/
ComboBoxComponent.prototype.handleFocus = function () {
this.isFocused = true;
this.onFocus.emit();
};
ComboBoxComponent.prototype.change = function (candidate, isCustom) {
if (isCustom === void 0) { isCustom = false; }
this.popupOpen = false;
if (isCustom) {
this.customValueSubject.next(candidate);
}
else {
this.valueSubject.next(candidate);
}
};
ComboBoxComponent.prototype.emitChange = function () {
var _this = this;
this._previousValue = this.dataItem;
this.selectionSubject.next(this.data.findIndex(function (element) {
return util_1.getter(element, _this.valueField) === util_1.getter(_this.value, _this.valueField);
}));
this.onChangeCallback(this.value);
this.valueChange.emit(this.value);
};
/**
* @hidden
*/
ComboBoxComponent.prototype.iconClick = function () {
this.searchbar.focus();
this.popupOpen = !this.popupOpen;
};
Object.defineProperty(ComboBoxComponent.prototype, "listContainerClasses", {
get: function () {
var containerClasses = ['k-list-container', 'k-reset'];
if (this.popupSettings.popupClass) {
containerClasses.push(this.popupSettings.popupClass);
}
return containerClasses;
},
enumerable: true,
configurable: true
});
ComboBoxComponent.prototype._toggle = function (open) {
var _this = this;
this._open = open;
if (this.popupRef) {
this.popupRef.popupElement
.removeEventListener('mousedown', this.popupMouseDownHandler);
this.popupRef.close();
this.popupRef = null;
}
if (this._open) {
this.popupRef = this.popupService.open({
anchor: this.wrapper,
animate: this.popupSettings.animate,
appendTo: this.appendTo,
content: this.popupTemplate,
popupClass: this.listContainerClasses,
positionMode: 'absolute'
});
var popupWrapper = this.popupRef.popupElement;
var _a = this.width, min = _a.min, max = _a.max;
popupWrapper.addEventListener('mousedown', this.popupMouseDownHandler);
popupWrapper.style.minWidth = min;
popupWrapper.style.width = max;
popupWrapper.setAttribute("dir", this.direction);
this.popupRef.popupAnchorViewportLeave.subscribe(function () { return _this.popupOpen = false; });
}
};
return ComboBoxComponent;
}());
ComboBoxComponent.decorators = [
{ type: core_1.Component, args: [{
exportAs: 'kendoComboBox',
providers: [exports.COMBOBOX_VALUE_ACCESSOR, selection_service_1.SelectionService, navigation_service_1.NavigationService],
selector: 'kendo-combobox',
template: "\n <span #wrapper unselectable=\"on\" [ngClass]=\"wrapperClasses()\">\n <kendo-searchbar #searchbar\n [role]=\"'listbox'\"\n [id]=\"listBoxId\"\n [activeDescendant]=\"activeDescendant\"\n [userInput]=\"text\"\n [suggestedText]=\"getSuggestion()\"\n [disabled]=\"disabled\"\n [tabIndex]=\"tabIndex\"\n [popupOpen]=\"popupOpen\"\n [placeholder]=\"placeholder\"\n (onNavigate)=\"handleNavigate($event)\"\n (valueChange)=\"searchBarChange($event)\"\n (onBlur)=\"handleBlur()\"\n (onFocus)=\"handleFocus()\"\n ></kendo-searchbar>\n <span *ngIf=\"!loading && (clearButton && text?.length)\" class=\"k-icon k-clear-value k-i-close\" title=\"clear\" role=\"button\" tabindex=\"-1\" (click)=\"clearValue($event)\" (mousedown)=\"$event.preventDefault()\"></span>\n <span unselectable=\"on\"\n [ngClass]=\"{ 'k-select': true }\"\n (click)=\"iconClick()\"\n (mousedown)=\"$event.preventDefault()\" >\n <span [ngClass]=\"buttonClasses\"></span>\n </span>\n <ng-template #popupTemplate>\n <!--header template-->\n <ng-template *ngIf=\"headerTemplate\"\n [templateContext]=\"{\n templateRef: headerTemplate.templateRef\n }\">\n </ng-template>\n <!--list-->\n <kendo-list\n [id]=\"listBoxId\"\n [optionPrefix]=\"optionPrefix\"\n [data]=\"data\"\n [textField]=\"textField\"\n [valueField]=\"valueField\"\n [template]=\"template\"\n [height]=\"height\"\n [show]=\"popupOpen\"\n >\n </kendo-list>\n <!--no-data template-->\n <div class=\"k-nodata\" *ngIf=\"data.length === 0\">\n <ng-template [ngIf]=\"noDataTemplate\"\n [templateContext]=\"{\n templateRef: noDataTemplate ? noDataTemplate.templateRef : undefined\n }\">\n </ng-template>\n <ng-template [ngIf]=\"!noDataTemplate\">\n <div>NO DATA FOUND.</div>\n </ng-template>\n </div>\n <!--footer template-->\n <ng-template *ngIf=\"footerTemplate\"\n [templateContext]=\"{\n templateRef: footerTemplate.templateRef\n }\">\n </ng-template>\n </ng-template>\n </span>\n <ng-template [ngIf]=\"popupOpen\">\n <kendo-resize-sensor (resize)=\"onResize()\"></kendo-resize-sensor>\n </ng-template>\n <ng-container #container></ng-container>\n "
},] },
];
/** @nocollapse */
ComboBoxComponent.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: core_1.Optional }, { type: core_1.Inject, args: [kendo_angular_l10n_1.RTL,] },] },
{ type: kendo_angular_popup_1.PopupService, },
{ type: selection_service_1.SelectionService, },
{ type: navigation_service_1.NavigationService, },
{ type: core_1.ChangeDetectorRef, },
{ type: core_1.ElementRef, },
]; };
ComboBoxComponent.propDecorators = {
'allowCustom': [{ type: core_1.Input },],
'data': [{ type: core_1.Input },],
'value': [{ type: core_1.Input },],
'textField': [{ type: core_1.Input },],
'valueField': [{ type: core_1.Input },],
'valuePrimitive': [{ type: core_1.Input },],
'valueNormalizer': [{ type: core_1.Input },],
'placeholder': [{ type: core_1.Input },],
'popupSettings': [{ type: core_1.Input },],
'iconClass': [{ type: core_1.Input },],
'loading': [{ type: core_1.Input },],
'suggest': [{ type: core_1.Input },],
'clearButton': [{ type: core_1.Input },],
'disabled': [{ type: core_1.Input },],
'tabIndex': [{ type: core_1.Input },],
'filterable': [{ type: core_1.Input },],
'valueChange': [{ type: core_1.Output },],
'selectionChange': [{ type: core_1.Output },],
'filterChange': [{ type: core_1.Output },],
'open': [{ type: core_1.Output },],
'close': [{ type: core_1.Output },],
'onFocus': [{ type: core_1.Output, args: ['focus',] },],
'onBlur': [{ type: core_1.Output, args: ['blur',] },],
'template': [{ type: core_1.ContentChild, args: [item_template_directive_1.ItemTemplateDirective,] },],
'headerTemplate': [{ type: core_1.ContentChild, args: [header_template_directive_1.HeaderTemplateDirective,] },],
'footerTemplate': [{ type: core_1.ContentChild, args: [footer_template_directive_1.FooterTemplateDirective,] },],
'noDataTemplate': [{ type: core_1.ContentChild, args: [no_data_template_directive_1.NoDataTemplateDirective,] },],
'container': [{ type: core_1.ViewChild, args: ['container', { read: core_1.ViewContainerRef },] },],
'popupTemplate': [{ type: core_1.ViewChild, args: ['popupTemplate',] },],
'searchbar': [{ type: core_1.ViewChild, args: [searchbar_component_1.SearchBarComponent,] },],
'widgetClasses': [{ type: core_1.HostBinding, args: ['class.k-widget',] }, { type: core_1.HostBinding, args: ['class.k-combobox',] }, { type: core_1.HostBinding, args: ['class.k-header',] },],
'clearable': [{ type: core_1.HostBinding, args: ['class.k-combobox-clearable',] },],
'widgetHeight': [{ type: core_1.HostBinding, args: ['style.max-height',] },],
'dir': [{ type: core_1.HostBinding, args: ['attr.dir',] },],
};
exports.ComboBoxComponent = ComboBoxComponent;