| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- /**
- * DevExtreme (ui/select_box.js)
- * Version: 19.1.16
- * Build date: Tue Oct 18 2022
- *
- * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
- * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
- */
- "use strict";
- var $ = require("../core/renderer");
- var commonUtils = require("../core/utils/common");
- var typeUtils = require("../core/utils/type");
- var isDefined = typeUtils.isDefined;
- var isPromise = typeUtils.isPromise;
- var extend = require("../core/utils/extend").extend;
- var inArray = require("../core/utils/array").inArray;
- var each = require("../core/utils/iterator").each;
- var deferredUtils = require("../core/utils/deferred");
- var getPublicElement = require("../core/utils/dom").getPublicElement;
- var Deferred = deferredUtils.Deferred;
- var errors = require("../core/errors");
- var domAdapter = require("../core/dom_adapter");
- var inkRipple = require("./widget/utils.ink_ripple");
- var messageLocalization = require("../localization/message");
- var registerComponent = require("../core/component_registrator");
- var DropDownList = require("./drop_down_editor/ui.drop_down_list");
- var DISABLED_STATE_SELECTOR = ".dx-state-disabled";
- var SELECTBOX_CLASS = "dx-selectbox";
- var SELECTBOX_POPUP_CLASS = "dx-selectbox-popup";
- var SELECTBOX_CONTAINER_CLASS = "dx-selectbox-container";
- var SELECTBOX_POPUP_WRAPPER_CLASS = "dx-selectbox-popup-wrapper";
- var SelectBox = DropDownList.inherit({
- _supportedKeys: function() {
- var that = this;
- var parent = this.callBase();
- var clearSelectBox = function(e) {
- var isEditable = this._isEditable();
- if (!isEditable) {
- if (this.option("showClearButton")) {
- e.preventDefault();
- this.reset()
- }
- } else {
- if (this._valueSubstituted()) {
- this._preventFiltering = true
- }
- }
- this._preventSubstitution = true
- };
- var searchIfNeeded = function() {
- if (that.option("searchEnabled") && that._valueSubstituted()) {
- that._searchHandler()
- }
- };
- return extend({}, parent, {
- tab: function() {
- if (this.option("opened") && "instantly" === this.option("applyValueMode")) {
- this._cleanInputSelection()
- }
- if (this._wasSearch()) {
- this._clearFilter()
- }
- parent.tab && parent.tab.apply(this, arguments)
- },
- upArrow: function() {
- if (parent.upArrow && parent.upArrow.apply(this, arguments)) {
- if (!this.option("opened")) {
- this._setNextValue(-1)
- }
- return true
- }
- },
- downArrow: function() {
- if (parent.downArrow && parent.downArrow.apply(this, arguments)) {
- if (!this.option("opened")) {
- this._setNextValue(1)
- }
- return true
- }
- },
- leftArrow: function() {
- searchIfNeeded();
- parent.leftArrow && parent.leftArrow.apply(this, arguments)
- },
- rightArrow: function() {
- searchIfNeeded();
- parent.rightArrow && parent.rightArrow.apply(this, arguments)
- },
- home: function() {
- searchIfNeeded();
- parent.home && parent.home.apply(this, arguments)
- },
- end: function() {
- searchIfNeeded();
- parent.end && parent.end.apply(this, arguments)
- },
- escape: function() {
- var result = parent.escape && parent.escape.apply(this, arguments);
- this._cancelEditing();
- return isDefined(result) ? result : true
- },
- enter: function(e) {
- var isOpened = this.option("opened");
- var inputText = this._input().val().trim();
- var isCustomText = inputText && this._list && !this._list.option("focusedElement");
- if (!inputText && this.option("value") && this.option("allowClearing")) {
- this.option({
- selectedItem: null,
- value: null
- });
- this.close()
- } else {
- if (this.option("acceptCustomValue")) {
- e.preventDefault();
- if (isCustomText) {
- this._valueChangeEventHandler(e);
- if (isOpened) {
- this._toggleOpenState()
- }
- }
- return isOpened
- }
- if (parent.enter && parent.enter.apply(this, arguments)) {
- return isOpened
- }
- }
- },
- space: function(e) {
- var isOpened = this.option("opened");
- var isSearchEnabled = this.option("searchEnabled");
- var acceptCustomValue = this.option("acceptCustomValue");
- if (!isOpened || isSearchEnabled || acceptCustomValue) {
- return
- }
- e.preventDefault();
- this._valueChangeEventHandler(e);
- return true
- },
- backspace: clearSelectBox,
- del: clearSelectBox
- })
- },
- _getDefaultOptions: function() {
- return extend(this.callBase(), {
- placeholder: messageLocalization.format("Select"),
- fieldTemplate: null,
- valueChangeEvent: "change",
- acceptCustomValue: false,
- onCustomItemCreating: function(e) {
- if (!isDefined(e.customItem)) {
- e.customItem = e.text
- }
- },
- showSelectionControls: false,
- autocompletionEnabled: true,
- allowClearing: true,
- tooltipEnabled: false,
- openOnFieldClick: true,
- showDropDownButton: true,
- displayCustomValue: false,
- _isAdaptablePopupPosition: false,
- useInkRipple: false,
- useHiddenSubmitElement: true
- })
- },
- _init: function() {
- this.callBase();
- this._initCustomItemCreatingAction()
- },
- _initMarkup: function() {
- this.$element().addClass(SELECTBOX_CLASS);
- this._renderTooltip();
- this.option("useInkRipple") && this._renderInkRipple();
- this.callBase();
- this._$container.addClass(SELECTBOX_CONTAINER_CLASS)
- },
- _renderInkRipple: function() {
- this._inkRipple = inkRipple.render()
- },
- _toggleActiveState: function($element, value, e) {
- this.callBase.apply(this, arguments);
- if (!this._inkRipple || this._isEditable()) {
- return
- }
- var config = {
- element: this._inputWrapper(),
- event: e
- };
- if (value) {
- this._inkRipple.showWave(config)
- } else {
- this._inkRipple.hideWave(config)
- }
- },
- _createPopup: function() {
- this.callBase();
- this._popup.$element().addClass(SELECTBOX_POPUP_CLASS)
- },
- _popupWrapperClass: function() {
- return this.callBase() + " " + SELECTBOX_POPUP_WRAPPER_CLASS
- },
- _cancelEditing: function() {
- if (!this.option("searchEnabled") && this._list) {
- this._focusListElement(null);
- this._updateField(this.option("selectedItem"))
- }
- },
- _renderOpenedState: function() {
- this.callBase();
- if (this.option("opened")) {
- this._scrollToSelectedItem();
- this._focusSelectedElement()
- }
- },
- _focusSelectedElement: function() {
- var searchValue = this._searchValue();
- if (!searchValue) {
- this._focusListElement(null);
- return
- }
- var $listItems = this._list._itemElements();
- var index = inArray(this.option("selectedItem"), this.option("items"));
- var focusedElement = index >= 0 && !this._isCustomItemSelected() ? $listItems.eq(index) : null;
- this._focusListElement(focusedElement)
- },
- _renderFocusedElement: function() {
- if (!this._list) {
- return
- }
- var searchValue = this._searchValue();
- if (!searchValue || this.option("acceptCustomValue")) {
- this._focusListElement(null);
- return
- }
- var $listItems = this._list._itemElements();
- var focusedElement = $listItems.not(DISABLED_STATE_SELECTOR).eq(0);
- this._focusListElement(focusedElement)
- },
- _focusListElement: function(element) {
- this._preventInputValueRender = true;
- this._list.option("focusedElement", getPublicElement(element));
- delete this._preventInputValueRender
- },
- _scrollToSelectedItem: function() {
- this._list && this._list.scrollToItem(this._list.option("selectedItem"))
- },
- _listContentReadyHandler: function() {
- this.callBase();
- var isPaginate = this._dataSource && this._dataSource.paginate();
- if (isPaginate && this._needPopupRepaint()) {
- return
- }
- this._scrollToSelectedItem()
- },
- _renderValue: function() {
- this._renderInputValue();
- this._setSubmitValue();
- return (new Deferred).resolve()
- },
- _renderInputValue: function() {
- return this.callBase().always(function() {
- this._renderInputValueAsync()
- }.bind(this))
- },
- _renderInputValueAsync: function() {
- this._renderTooltip();
- this._renderInputValueImpl().always(function() {
- this._refreshSelected()
- }.bind(this))
- },
- _renderInputValueImpl: function() {
- this._renderField();
- return (new Deferred).resolve()
- },
- _setNextItem: function(step) {
- var item = this._calcNextItem(step);
- var value = this._valueGetter(item);
- this._setValue(value)
- },
- _setNextValue: function(step) {
- var dataSourceIsLoaded = this._dataSource.isLoaded() ? (new Deferred).resolve() : this._dataSource.load();
- dataSourceIsLoaded.done(function() {
- var selectedIndex = this._getSelectedIndex();
- var hasPages = this._dataSource.pageSize();
- var isLastPage = this._dataSource.isLastPage();
- var isLastItem = selectedIndex === this._items().length - 1;
- if (hasPages && !isLastPage && isLastItem && step > 0) {
- if (!this._popup) {
- this._createPopup()
- }
- if (!this._dataSource.isLoading()) {
- this._list._loadNextPage().done(this._setNextItem.bind(this, step))
- }
- } else {
- this._setNextItem(step)
- }
- }.bind(this))
- },
- _setSelectedItem: function(item) {
- var isUnknownItem = !this._isCustomValueAllowed() && void 0 === item;
- this.callBase(isUnknownItem ? null : item);
- if (!isUnknownItem && (!this._isEditable() || this._isCustomItemSelected())) {
- this._setListOption("selectedItem", this.option("selectedItem"))
- }
- },
- _isCustomValueAllowed: function() {
- return this.option("acceptCustomValue") || this.callBase()
- },
- _displayValue: function(item) {
- item = !isDefined(item) && this._isCustomValueAllowed() ? this.option("value") : item;
- return this.callBase(item)
- },
- _listConfig: function() {
- var result = extend(this.callBase(), {
- pageLoadMode: "scrollBottom",
- onSelectionChanged: this._getSelectionChangeHandler(),
- selectedItem: this.option("selectedItem"),
- onFocusedItemChanged: this._listFocusedItemChangeHandler.bind(this)
- });
- if (this.option("showSelectionControls")) {
- extend(result, {
- showSelectionControls: true,
- selectionByClick: true
- })
- }
- return result
- },
- _listFocusedItemChangeHandler: function(e) {
- if (this._preventInputValueRender) {
- return
- }
- var list = e.component;
- var focusedElement = $(list.option("focusedElement"));
- var focusedItem = list._getItemData(focusedElement);
- this._updateField(focusedItem)
- },
- _updateField: function(item) {
- var fieldTemplate = this._getTemplateByOption("fieldTemplate");
- if (!(fieldTemplate && this.option("fieldTemplate"))) {
- this._renderDisplayText(this._displayGetter(item));
- return
- }
- this._renderField()
- },
- _getSelectionChangeHandler: function() {
- return this.option("showSelectionControls") ? this._selectionChangeHandler.bind(this) : commonUtils.noop
- },
- _selectionChangeHandler: function(e) {
- each(e.addedItems || [], function(_, addedItem) {
- this._setValue(this._valueGetter(addedItem))
- }.bind(this))
- },
- _getActualSearchValue: function() {
- return this._dataSource.searchValue()
- },
- _toggleOpenState: function(isVisible) {
- if (this.option("disabled")) {
- return
- }
- isVisible = arguments.length ? isVisible : !this.option("opened");
- if (!isVisible) {
- this._restoreInputText(true)
- }
- if (this._wasSearch() && isVisible) {
- this._wasSearch(false);
- var showDataImmediately = this.option("showDataBeforeSearch") || 0 === this.option("minSearchLength");
- if (showDataImmediately && this._dataSource) {
- if (this._searchTimer) {
- return
- }
- var searchValue = this._getActualSearchValue();
- searchValue && this._wasSearch(true);
- this._filterDataSource(searchValue || null)
- } else {
- this._setListOption("items", [])
- }
- }
- if (isVisible) {
- this._scrollToSelectedItem()
- }
- this.callBase(isVisible)
- },
- _renderTooltip: function() {
- if (this.option("tooltipEnabled")) {
- this.$element().attr("title", this.option("displayValue"))
- }
- },
- _renderDimensions: function() {
- this.callBase();
- this._setPopupOption("width")
- },
- _isValueEqualInputText: function() {
- var initialSelectedItem = this.option("selectedItem");
- var value = this._displayGetter(initialSelectedItem);
- var displayValue = value ? String(value) : "";
- var inputText = this._searchValue();
- return displayValue === inputText
- },
- _popupHidingHandler: function() {
- if (this._isValueEqualInputText()) {
- this._cancelEditing()
- }
- this.callBase()
- },
- _restoreInputText: function(saveEditingValue) {
- if (this.option("readOnly")) {
- return
- }
- this._loadItemDeferred && this._loadItemDeferred.always(function() {
- var initialSelectedItem = this.option("selectedItem");
- if (this.option("acceptCustomValue")) {
- if (!saveEditingValue) {
- this._updateField(initialSelectedItem);
- this._clearFilter()
- }
- return
- }
- if (this.option("searchEnabled")) {
- if (!this._searchValue() && this.option("allowClearing")) {
- this._clearTextValue();
- return
- }
- }
- if (this._isValueEqualInputText()) {
- return
- }
- this._renderInputValue().always(function(selectedItem) {
- var newSelectedItem = commonUtils.ensureDefined(selectedItem, initialSelectedItem);
- this._setSelectedItem(newSelectedItem);
- this._updateField(newSelectedItem);
- this._clearFilter()
- }.bind(this))
- }.bind(this))
- },
- _focusOutHandler: function(e) {
- if (!this._preventNestedFocusEvent(e)) {
- this._clearSearchTimer();
- this._restoreInputText();
- var shouldCancelSearch = this._wasSearch() && !this.option("acceptCustomValue") && this.option("searchEnabled") && this.option("opened") && !this._isOverlayNestedTarget(e.relatedTarget);
- if (shouldCancelSearch) {
- this._searchCanceled()
- }
- }
- this.callBase(e)
- },
- _isOverlayNestedTarget: function(target) {
- return !!$(target).closest(".".concat(SELECTBOX_POPUP_WRAPPER_CLASS)).length
- },
- _clearTextValue: function() {
- this.option("value", null)
- },
- _shouldOpenPopup: function() {
- return this._needPassDataSourceToList()
- },
- _isFocused: function() {
- var activeElement = domAdapter.getActiveElement();
- return this.callBase() && $(activeElement).closest(this._input()).length > 0
- },
- _renderValueChangeEvent: function() {
- if (this._isEditable()) {
- this.callBase()
- }
- },
- _isEditable: function() {
- return this.option("acceptCustomValue") || this.option("searchEnabled")
- },
- _fieldRenderData: function() {
- var $listFocused = this._list && this.option("opened") && $(this._list.option("focusedElement"));
- if ($listFocused && $listFocused.length) {
- return this._list._getItemData($listFocused)
- }
- return this.option("selectedItem")
- },
- _readOnlyPropValue: function() {
- return !this._isEditable() || this.option("readOnly")
- },
- _isSelectedValue: function(value) {
- return this._isValueEquals(value, this.option("value"))
- },
- _shouldCloseOnItemClick: function() {
- return !(this.option("showSelectionControls") && "single" !== this.option("selectionMode"))
- },
- _listItemClickHandler: function(e) {
- var previousValue = this._getCurrentValue();
- this._focusListElement($(e.itemElement));
- this._saveValueChangeEvent(e.event);
- if (this._shouldClearFilter()) {
- this._clearFilter()
- }
- this._completeSelection(this._valueGetter(e.itemData));
- if (this._shouldCloseOnItemClick()) {
- this.option("opened", false)
- }
- if (this.option("searchEnabled") && previousValue === this._valueGetter(e.itemData)) {
- this._updateField(e.itemData)
- }
- },
- _shouldClearFilter: function() {
- return this._wasSearch()
- },
- _completeSelection: function(value) {
- this._setValue(value)
- },
- _loadItem: function(value, cache) {
- var that = this;
- var deferred = new Deferred;
- this.callBase(value, cache).done(function(item) {
- deferred.resolve(item)
- }.bind(this)).fail(function() {
- var selectedItem = that.option("selectedItem");
- if (that.option("acceptCustomValue") && value === that._valueGetter(selectedItem)) {
- deferred.resolve(selectedItem)
- } else {
- deferred.reject()
- }
- }.bind(this));
- return deferred.promise()
- },
- _loadInputValue: function(value, callback) {
- this._loadItemDeferred = this._loadItem(value).always(callback);
- return this._loadItemDeferred
- },
- _isCustomItemSelected: function() {
- var selectedItem = this.option("selectedItem");
- var searchValue = this._searchValue();
- var selectedItemText = this._displayGetter(selectedItem);
- return !selectedItemText || searchValue !== selectedItemText.toString()
- },
- _valueChangeEventHandler: function(e) {
- if (this.option("acceptCustomValue") && this._isCustomItemSelected()) {
- this._customItemAddedHandler(e)
- }
- },
- _initCustomItemCreatingAction: function() {
- this._customItemCreatingAction = this._createActionByOption("onCustomItemCreating")
- },
- _createCustomItem: function(text) {
- var params = {
- text: text
- };
- var actionResult = this._customItemCreatingAction(params);
- var item = commonUtils.ensureDefined(actionResult, params.customItem);
- if (isDefined(actionResult)) {
- errors.log("W0015", "onCustomItemCreating", "customItem")
- }
- return item
- },
- _customItemAddedHandler: function(e) {
- var searchValue = this._searchValue();
- var item = this._createCustomItem(searchValue);
- this._saveValueChangeEvent(e);
- if (void 0 === item) {
- this._renderValue();
- throw errors.Error("E0121")
- }
- if (isPromise(item)) {
- deferredUtils.fromPromise(item).done(this._setCustomItem.bind(this)).fail(this._setCustomItem.bind(this, null))
- } else {
- this._setCustomItem(item)
- }
- },
- _setCustomItem: function(item) {
- if (this._disposed) {
- return
- }
- item = item || null;
- this.option("selectedItem", item);
- if (this._shouldClearFilter()) {
- this._filterDataSource(null)
- }
- this._setValue(this._valueGetter(item));
- this._renderDisplayText(this._displayGetter(item))
- },
- _clearValueHandler: function(e) {
- this.callBase(e);
- return false
- },
- _wasSearch: function(value) {
- if (!arguments.length) {
- return this._wasSearchValue
- }
- this._wasSearchValue = value
- },
- _searchHandler: function(e) {
- if (this._preventFiltering) {
- delete this._preventFiltering;
- return
- }
- if (this._needPassDataSourceToList()) {
- this._wasSearch(true)
- }
- this.callBase(e)
- },
- _dataSourceFiltered: function(searchValue) {
- this.callBase();
- if (null !== searchValue) {
- this._renderInputSubstitution();
- this._renderFocusedElement()
- }
- },
- _valueSubstituted: function() {
- var input = this._input().get(0);
- var isAllSelected = 0 === input.selectionStart && input.selectionEnd === this._searchValue().length;
- var inputHasSelection = input.selectionStart !== input.selectionEnd;
- return this._wasSearch() && inputHasSelection && !isAllSelected
- },
- _shouldSubstitutionBeRendered: function() {
- return this.option("autocompletionEnabled") && !this._preventSubstitution && this.option("searchEnabled") && !this.option("acceptCustomValue") && "startswith" === this.option("searchMode")
- },
- _renderInputSubstitution: function() {
- if (!this._shouldSubstitutionBeRendered()) {
- delete this._preventSubstitution;
- return
- }
- var item = this._list && this._getPlainItems(this._list.option("items"))[0];
- if (!item) {
- return
- }
- var $input = this._input();
- var valueLength = $input.val().length;
- if (0 === valueLength) {
- return
- }
- var inputElement = $input.get(0);
- var displayValue = this._displayGetter(item).toString();
- inputElement.value = displayValue;
- this._caret({
- start: valueLength,
- end: displayValue.length
- })
- },
- _cleanInputSelection: function() {
- var inputElement = this._input().get(0);
- var endPosition = inputElement.value.length;
- inputElement.selectionStart = endPosition;
- inputElement.selectionEnd = endPosition
- },
- _dispose: function() {
- this._renderInputValueAsync = commonUtils.noop;
- delete this._loadItemDeferred;
- this.callBase()
- },
- _optionChanged: function(args) {
- switch (args.name) {
- case "_isAdaptablePopupPosition":
- case "autocompletionEnabled":
- break;
- case "onCustomItemCreating":
- this._initCustomItemCreatingAction();
- break;
- case "tooltipEnabled":
- this._renderTooltip();
- break;
- case "displayCustomValue":
- case "acceptCustomValue":
- case "showSelectionControls":
- case "useInkRipple":
- this._invalidate();
- break;
- case "allowClearing":
- break;
- default:
- this.callBase(args)
- }
- },
- _clean: function() {
- delete this._inkRipple;
- this.callBase()
- }
- });
- registerComponent("dxSelectBox", SelectBox);
- module.exports = SelectBox;
- module.exports.default = module.exports;
|