devextreme
Version:
JavaScript/TypeScript Component Suite for Responsive Web Development
1,144 lines (1,143 loc) • 45.1 kB
JavaScript
/**
* DevExtreme (esm/__internal/ui/lookup.js)
* Version: 26.1.4
* Build date: Fri Jul 24 2026
*
* Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import {
locate,
move,
resetPosition
} from "../../common/core/animation/translator";
import eventsEngine from "../../common/core/events/core/events_engine";
import messageLocalization from "../../common/core/localization/message";
import registerComponent from "../../core/component_registrator";
import devices from "../../core/devices";
import {
getPublicElement
} from "../../core/element";
import {
getFieldName
} from "../../core/options/utils";
import $ from "../../core/renderer";
import {
ChildDefaultTemplate
} from "../../core/templates/child_default_template";
import {
noop
} from "../../core/utils/common";
import {
extend
} from "../../core/utils/extend";
import {
getHeight,
getOuterHeight,
getOuterWidth,
getWidth
} from "../../core/utils/size";
import {
isDefined
} from "../../core/utils/type";
import {
getWindow
} from "../../core/utils/window";
import Popover from "../../ui/popover/ui.popover";
import {
current,
isMaterial
} from "../../ui/themes";
import supportUtils from "../core/utils/m_support";
import DropDownList from "../ui/drop_down_editor/drop_down_list";
import {
getElementWidth
} from "../ui/drop_down_editor/utils";
import TextBox from "../ui/text_box/text_box";
const window = getWindow();
const LOOKUP_CLASS = "dx-lookup";
const LOOKUP_SEARCH_CLASS = "dx-lookup-search";
const LOOKUP_SEARCH_WRAPPER_CLASS = "dx-lookup-search-wrapper";
const LOOKUP_FIELD_CLASS = "dx-lookup-field";
const LOOKUP_ARROW_CLASS = "dx-lookup-arrow";
const LOOKUP_FIELD_WRAPPER_CLASS = "dx-lookup-field-wrapper";
const LOOKUP_POPUP_CLASS = "dx-lookup-popup";
const LOOKUP_POPUP_WRAPPER_CLASS = "dx-lookup-popup-wrapper";
const LOOKUP_POPUP_SEARCH_CLASS = "dx-lookup-popup-search";
const LOOKUP_POPOVER_MODE = "dx-lookup-popover-mode";
const LOOKUP_EMPTY_CLASS = "dx-lookup-empty";
const LOOKUP_POPOVER_FLIP_VERTICAL_CLASS = "dx-popover-flipped-vertical";
const TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input";
const TEXTEDITOR_EMPTY_CLASS = "dx-texteditor-empty";
const LIST_ITEM_CLASS = "dx-list-item";
const LIST_ITEM_SELECTED_CLASS = "dx-list-item-selected";
const GROUP_LIST_HEADER_CLASS = "dx-list-group-header";
const MATERIAL_LOOKUP_LIST_ITEMS_COUNT = 5;
const MATERIAL_LOOKUP_LIST_PADDING = 8;
const WINDOW_RATIO = .8;
class Lookup extends DropDownList {
_supportedKeys() {
return Object.assign({}, super._supportedKeys(), {
space(e) {
e.preventDefault();
this._validatedOpening()
},
enter() {
this._validatedOpening()
}
})
}
_getDefaultOptions() {
const getSize = side => {
if ("phone" === devices.real().deviceType && window.visualViewport) {
return .8 * window.visualViewport[side]
}
const size = "width" === side ? getWidth(window) : getHeight(window);
return .8 * size
};
return Object.assign({}, super._getDefaultOptions(), {
placeholder: messageLocalization.format("Select"),
searchPlaceholder: messageLocalization.format("Search"),
searchEnabled: true,
searchStartEvent: "input change keyup",
cleanSearchOnOpening: true,
showCancelButton: true,
showClearButton: false,
clearButtonText: messageLocalization.format("Clear"),
applyButtonText: messageLocalization.format("OK"),
pullRefreshEnabled: false,
useNativeScrolling: true,
pullingDownText: messageLocalization.format("dxList-pullingDownText"),
pulledDownText: messageLocalization.format("dxList-pulledDownText"),
refreshingText: messageLocalization.format("dxList-refreshingText"),
pageLoadingText: messageLocalization.format("dxList-pageLoadingText"),
onScroll: void 0,
onPullRefresh: void 0,
onPageLoading: void 0,
pageLoadMode: "scrollBottom",
nextButtonText: messageLocalization.format("dxList-nextButtonText"),
grouped: false,
groupTemplate: "group",
usePopover: false,
openOnFieldClick: true,
showDropDownButton: false,
focusStateEnabled: false,
dropDownOptions: {
_ignoreFunctionValueDeprecation: true,
showTitle: true,
width: () => getSize("width"),
height: () => getSize("height"),
shading: true,
hideOnOutsideClick: true,
animation: {},
title: "",
titleTemplate: "title",
onTitleRendered: void 0,
fullScreen: false,
maxHeight: "100vh"
},
dropDownCentered: false,
_scrollToSelectedItemEnabled: false,
useHiddenSubmitElement: true
})
}
_defaultOptionsRules() {
const themeName = current();
return super._defaultOptionsRules().concat([{
device: () => !supportUtils.nativeScrolling,
options: {
useNativeScrolling: false
}
}, {
device: device => !devices.isSimulator() && "desktop" === devices.real().deviceType && "generic" === device.platform,
options: {
usePopover: true,
dropDownOptions: {
height: "auto"
}
}
}, {
device: {
platform: "ios",
phone: true
},
options: {
dropDownOptions: {
fullScreen: true
}
}
}, {
device: {
platform: "ios",
tablet: true
},
options: {
dropDownOptions: {
width: () => .4 * Math.min(getWidth(window), getHeight(window)),
height: "auto"
},
usePopover: true
}
}, {
device: () => "desktop" === devices.real().deviceType && !devices.isSimulator(),
options: {
focusStateEnabled: true
}
}, {
device: () => isMaterial(themeName),
options: {
usePopover: false,
searchEnabled: false,
showCancelButton: false,
dropDownCentered: true,
_scrollToSelectedItemEnabled: true,
dropDownOptions: {
shading: false,
showTitle: false,
height: () => this._getPopupHeight(),
width: () => getElementWidth(this.$element())
}
}
}])
}
_init() {
super._init();
this._initActions()
}
_initActions() {
super._initActions();
this._initScrollAction();
this._initPageLoadingAction();
this._initPullRefreshAction()
}
_initPageLoadingAction() {
this._pageLoadingAction = this._createActionByOption("onPageLoading")
}
_initPullRefreshAction() {
this._pullRefreshAction = this._createActionByOption("onPullRefresh")
}
_initScrollAction() {
this._scrollAction = this._createActionByOption("onScroll")
}
_scrollHandler(e) {
var _this$_scrollAction;
null === (_this$_scrollAction = this._scrollAction) || void 0 === _this$_scrollAction || _this$_scrollAction.call(this, e)
}
_pullRefreshHandler(e) {
var _this$_pullRefreshAct;
null === (_this$_pullRefreshAct = this._pullRefreshAction) || void 0 === _this$_pullRefreshAct || _this$_pullRefreshAct.call(this, e)
}
_pageLoadingHandler(e) {
var _this$_pageLoadingAct;
null === (_this$_pageLoadingAct = this._pageLoadingAction) || void 0 === _this$_pageLoadingAct || _this$_pageLoadingAct.call(this, e)
}
_initTemplates() {
super._initTemplates();
this._templateManager.addDefaultTemplates({
group: new ChildDefaultTemplate("group"),
title: new ChildDefaultTemplate("title")
})
}
_initMarkup() {
const {
usePopover: usePopover
} = this.option();
this.$element().addClass("dx-lookup").toggleClass(LOOKUP_POPOVER_MODE, usePopover);
super._initMarkup()
}
_inputWrapper() {
return this.$element().find(".dx-lookup-field-wrapper")
}
_dataSourceOptions() {
return Object.assign({}, super._dataSourceOptions(), {
paginate: true
})
}
_fireContentReadyAction() {}
_popupWrapperClass() {
return ""
}
_renderInput() {
const {
inputAttr: inputAttr
} = this.option();
this._$field = $("<div>");
this._applyInputAttributes(inputAttr);
this._$field.addClass("dx-lookup-field");
const $arrow = $("<div>").addClass("dx-lookup-arrow");
this._$fieldWrapper = $("<div>").addClass("dx-lookup-field-wrapper").append(this._$field).append($arrow).appendTo(this.$element())
}
_applyInputAttributes(attributes) {
this._$field.attr(attributes)
}
_getInputContainer() {
return this._$fieldWrapper
}
_renderField() {
const {
fieldTemplate: fieldTemplateOption,
displayValue: displayValue,
selectedItem: selectedItem
} = this.option();
const fieldTemplate = this._getTemplate(fieldTemplateOption);
if (fieldTemplate && fieldTemplateOption) {
this._renderFieldTemplate(fieldTemplate);
return
}
this._updateField(displayValue);
const isFieldEmpty = !selectedItem;
this.$element().toggleClass("dx-lookup-empty", isFieldEmpty).toggleClass("dx-texteditor-empty", isFieldEmpty)
}
_getLabelContainer() {
return this._$field
}
_renderDisplayText(text) {
if (this._input().length) {
super._renderDisplayText(text)
} else {
this._updateField(text)
}
}
_updateField(text) {
const displayText = isDefined(text) && String(text);
this._$field.empty();
if (displayText) {
this._$field.text(displayText)
} else {
const {
placeholder: placeholder
} = this.option();
const $placeholder = $("<div>").attr({
"data-dx_placeholder": placeholder
});
this._$field.append($placeholder);
$placeholder.addClass("dx-placeholder")
}
}
_renderButtonContainers() {}
_renderFieldTemplate(template) {
this._$field.empty();
const data = this._fieldRenderData();
template.render({
model: data,
container: getPublicElement(this._$field)
})
}
_fieldRenderData() {
const {
selectedItem: selectedItem
} = this.option();
return selectedItem
}
_popupShowingHandler() {
var _this$_searchBox;
super._popupShowingHandler();
const {
cleanSearchOnOpening: cleanSearchOnOpening,
searchEnabled: searchEnabled,
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled,
dropDownOptions: {
fullScreen: fullScreen
} = {}
} = this.option();
const {
value: searchBoxValue
} = (null === (_this$_searchBox = this._searchBox) || void 0 === _this$_searchBox ? void 0 : _this$_searchBox.option()) ?? {};
if (cleanSearchOnOpening) {
var _this$_list;
if (searchEnabled && searchBoxValue) {
var _this$_searchBox2;
null === (_this$_searchBox2 = this._searchBox) || void 0 === _this$_searchBox2 || _this$_searchBox2.option("value", "");
this._searchCanceled()
}
null === (_this$_list = this._list) || void 0 === _this$_list || _this$_list.option("focusedElement", null)
}
if (fullScreen && _scrollToSelectedItemEnabled) {
var _this$_popup;
const {
position: position
} = (null === (_this$_popup = this._popup) || void 0 === _this$_popup ? void 0 : _this$_popup.option()) ?? {};
if (position) {
position.of = $(window)
}
}
}
_popupShownHandler() {
const {
_scrollToSelectedItemEnabled: scrollToSelectedItemEnabled,
dropDownOptions: {
fullScreen: fullScreen
} = {}
} = this.option();
if (!fullScreen && scrollToSelectedItemEnabled) {
this._setPopupPosition()
}
super._popupShownHandler()
}
_scrollToSelectedItem() {
var _this$_list2;
const {
selectedIndex: selectedIndex,
items: listItems,
grouped: grouped
} = (null === (_this$_list2 = this._list) || void 0 === _this$_list2 ? void 0 : _this$_list2.option()) ?? {};
const itemsCount = (null === listItems || void 0 === listItems ? void 0 : listItems.length) ?? 0;
if (0 !== itemsCount) {
var _this$_list5;
if (grouped) {
var _this$_list3;
null === (_this$_list3 = this._list) || void 0 === _this$_list3 || _this$_list3.scrollToItem({
group: itemsCount - 1,
item: ((null === listItems || void 0 === listItems ? void 0 : listItems[itemsCount - 1].items.length) ?? 0) - 1
})
} else {
var _this$_list4;
null === (_this$_list4 = this._list) || void 0 === _this$_list4 || _this$_list4.scrollToItem(itemsCount - 1)
}
null === (_this$_list5 = this._list) || void 0 === _this$_list5 || _this$_list5.scrollToItem(selectedIndex)
}
}
_getDifferenceOffsets(selectedListItem) {
var _selectedListItem$off, _$$offset;
return ((null === (_selectedListItem$off = selectedListItem.offset()) || void 0 === _selectedListItem$off ? void 0 : _selectedListItem$off.top) ?? 0) - ((null === (_$$offset = $(this.element()).offset()) || void 0 === _$$offset ? void 0 : _$$offset.top) ?? 0)
}
_isCenteringEnabled(index, count) {
return index > 1 && index < count - 2
}
_getPopupOffset() {
var _this$_list6, _$$offset2, _this$_list7;
const listItemsCount = this._listItemElements().length;
if (0 === listItemsCount) {
return
}
const selectedListItem = $(null === (_this$_list6 = this._list) || void 0 === _this$_list6 ? void 0 : _this$_list6.element()).find(".dx-list-item-selected");
const selectedIndex = this._listItemElements().index(selectedListItem);
const differenceOfHeights = (getHeight(selectedListItem) - getHeight(this.element())) / 2;
const lookupOffset = (null === (_$$offset2 = $(null === (_this$_list7 = this._list) || void 0 === _this$_list7 ? void 0 : _this$_list7.element()).offset()) || void 0 === _$$offset2 ? void 0 : _$$offset2.top) ?? 0;
const {
dropDownOptions: {
height: dropDownHeightOption
} = {}
} = this.option();
const popupHeight = "function" === typeof dropDownHeightOption ? dropDownHeightOption() : dropDownHeightOption;
const windowHeight = getHeight(window);
let offsetTop = 0;
if (-1 !== selectedIndex) {
if (this._isCenteringEnabled(selectedIndex, listItemsCount)) {
this._scrollToSelectedItem();
const differenceOffset = this._getDifferenceOffsets(selectedListItem);
const scrollOffsetTop = (popupHeight - getHeight(selectedListItem)) / 2 - differenceOffset;
this._list.scrollTo(this._list.scrollTop() + 4 - scrollOffsetTop);
offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem);
if (lookupOffset < offsetTop && selectedIndex !== listItemsCount - 3) {
const updatedDifferenceOffset = this._getDifferenceOffsets(selectedListItem);
this._list.scrollTo(this._list.scrollTop() + updatedDifferenceOffset / 2);
offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
}
} else if (selectedIndex <= 1) {
this._list.scrollTo(0);
offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
} else if (selectedIndex >= listItemsCount - 2) {
this._scrollToSelectedItem();
offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
}
if (lookupOffset < offsetTop) {
this._scrollToSelectedItem();
offsetTop = differenceOfHeights + 8
}
}
const offsetBottom = popupHeight - offsetTop - getHeight(this.element());
if (windowHeight - lookupOffset < offsetBottom) {
this._list.scrollTo(this._list.scrollTop() + differenceOfHeights - offsetBottom);
offsetTop = popupHeight - getHeight(this.element()) - 8
}
return offsetTop
}
_setPopupPosition() {
var _this$_popup2, _this$_popup3;
const {
dropDownCentered: dropDownCentered
} = this.option();
if (!dropDownCentered) {
return
}
const flipped = null === (_this$_popup2 = this._popup) || void 0 === _this$_popup2 || null === (_this$_popup2 = _this$_popup2.$wrapper()) || void 0 === _this$_popup2 ? void 0 : _this$_popup2.hasClass("dx-popover-flipped-vertical");
if (flipped) {
return
}
const popupContentParent = $(null === (_this$_popup3 = this._popup) || void 0 === _this$_popup3 ? void 0 : _this$_popup3.$content()).parent();
const popupOffset = this._getPopupOffset() ?? 0;
const position = locate(popupContentParent);
move(popupContentParent, {
top: position.top - popupOffset
})
}
_listItemGroupedElements() {
const groupsContainer = this._list ? this._list._getItemsContainer().children() : [];
const groups = Array.from(groupsContainer);
const items = [];
groups.forEach(group => {
items.push($(group).find(".dx-list-group-header")[0]);
const groupedItems = Array.from($(group).find(".dx-list-item"));
items.push(...groupedItems)
});
return $(items)
}
_calculateListHeight(grouped) {
const listItems = grouped ? this._listItemGroupedElements() : this._listItemElements();
const selectedListItem = $(".dx-list-item-selected");
const selectedIndex = listItems.index(selectedListItem);
let listHeight = 0;
if (0 === listItems.length) {
listHeight += 8
} else if (listItems.length < 5) {
Array.from(listItems).forEach(item => {
listHeight += getOuterHeight(item)
})
} else {
let requireListItems = $([]);
if (selectedIndex <= 1) {
requireListItems = listItems.slice(0, 5)
} else if (this._isCenteringEnabled(selectedIndex, listItems.length)) {
requireListItems = listItems.slice(selectedIndex - 2, selectedIndex + 3)
} else {
const start = listItems.length - 5;
requireListItems = listItems.slice(start, listItems.length)
}
Array.from(requireListItems).forEach(item => {
listHeight += getOuterHeight(item)
})
}
return listHeight + (grouped ? 8 : 16)
}
_getPopupHeight() {
var _this$_list8, _this$_popup4, _this$_popup5;
const {
grouped: grouped
} = this.option();
if (!(null !== (_this$_list8 = this._list) && void 0 !== _this$_list8 && _this$_list8.itemElements().length)) {
return "auto"
}
const bottomToolbar = null === (_this$_popup4 = this._popup) || void 0 === _this$_popup4 ? void 0 : _this$_popup4.bottomToolbar();
const topToolbar = null === (_this$_popup5 = this._popup) || void 0 === _this$_popup5 ? void 0 : _this$_popup5.topToolbar();
return this._calculateListHeight(grouped) + (this._$searchWrapper ? getOuterHeight(this._$searchWrapper) : 0) + (bottomToolbar ? getOuterHeight(bottomToolbar) : 0) + (topToolbar ? getOuterHeight(topToolbar) : 0)
}
_allowSelectItemByTab() {
return false
}
_popupTabHandler(e) {
const shouldLoopFocusInsidePopup = this._shouldLoopFocusInsidePopup();
if (!shouldLoopFocusInsidePopup) {
super._popupTabHandler(e)
}
}
_renderPopup() {
var _this$_$popup, _this$_popup6;
const {
usePopover: usePopover,
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled,
dropDownOptions: {
fullScreen: fullScreen
} = {}
} = this.option();
if (usePopover && !fullScreen) {
if (_scrollToSelectedItemEnabled) {
super._renderPopup()
} else {
this._renderPopover();
this._attachPopupKeyHandler()
}
} else {
super._renderPopup()
}
null === (_this$_$popup = this._$popup) || void 0 === _this$_$popup || _this$_$popup.addClass("dx-lookup-popup");
null === (_this$_popup6 = this._popup) || void 0 === _this$_popup6 || null === (_this$_popup6 = _this$_popup6.$wrapper()) || void 0 === _this$_popup6 || _this$_popup6.addClass("dx-lookup-popup-wrapper")
}
_renderPopover() {
const popupConfig = this._popupConfig();
const options = extend(popupConfig, this._options.cache("dropDownOptions"), {
showEvent: null,
hideEvent: null,
target: this.$element(),
fullScreen: false,
shading: false,
hideOnParentScroll: true,
_fixWrapperPosition: false,
width: this._isInitialOptionValue("dropDownOptions.width") ? () => getOuterWidth(this.$element()) : popupConfig.width
});
this._popup = this._createComponent(this._$popup, Popover, options);
this._popup.$overlayContent().attr("role", "dialog");
this._popup.on({
showing: this._popupShowingHandler.bind(this),
shown: this._popupShownHandler.bind(this),
hiding: this._popupHidingHandler.bind(this),
hidden: this._popupHiddenHandler.bind(this),
contentReady: this._contentReadyHandler.bind(this)
});
const {
_scrollToSelectedItemEnabled: scrollToSelectedItemEnabledInPopover
} = this.option();
if (scrollToSelectedItemEnabledInPopover) {
this._popup._$arrow.remove()
}
const $content = this._popup.$content();
if ($content) {
this._setPopupContentId($content)
}
this._contentReadyHandler()
}
_popupHidingHandler() {
super._popupHidingHandler();
const {
focusStateEnabled: focusStateEnabled
} = this.option();
if (focusStateEnabled) {
this.focus()
}
}
_popupHiddenHandler() {
super._popupHiddenHandler();
const {
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
} = this.option();
if (_scrollToSelectedItemEnabled) {
var _this$_popup7;
resetPosition($(null === (_this$_popup7 = this._popup) || void 0 === _this$_popup7 ? void 0 : _this$_popup7.content()).parent())
}
}
_preventFocusOnPopup() {}
_shouldLoopFocusInsidePopup() {
const {
usePopover: usePopover,
dropDownCentered: dropDownCentered,
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
} = this.option();
const result = _scrollToSelectedItemEnabled ? Boolean(dropDownCentered) : !usePopover;
return result
}
_popupConfig() {
const {
dropDownOptions: dropDownOptions = {},
dropDownCentered: dropDownCentered,
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
} = this.option();
const shouldLoopFocusInsidePopup = this._shouldLoopFocusInsidePopup();
const result = Object.assign({}, super._popupConfig(), {
toolbarItems: this._getPopupToolbarItems(),
hideOnParentScroll: false,
onPositioned: null,
maxHeight: dropDownOptions.maxHeight,
showTitle: dropDownOptions.showTitle,
title: dropDownOptions.title,
titleTemplate: this._getTemplateByOption("dropDownOptions.titleTemplate"),
onTitleRendered: dropDownOptions.onTitleRendered,
fullScreen: dropDownOptions.fullScreen,
shading: dropDownOptions.shading,
hideOnOutsideClick: dropDownOptions.hideOnOutsideClick,
tabFocusLoopEnabled: shouldLoopFocusInsidePopup
});
delete result.animation;
delete result.position;
if (_scrollToSelectedItemEnabled) {
result.position = dropDownCentered ? {
my: "left top",
at: "left top",
of: this.element()
} : {
my: "left top",
at: "left bottom",
of: this.element()
};
result.hideOnParentScroll = true
} ["position", "animation", "width", "height"].forEach(optionName => {
const popupOptionValue = dropDownOptions[optionName];
if (void 0 !== popupOptionValue) {
result[optionName] = popupOptionValue
}
});
return result
}
_getPopupToolbarItems() {
const {
applyValueMode: applyValueMode
} = this.option();
const buttonsConfig = "useButtons" === applyValueMode ? this._popupToolbarItemsConfig() : [];
const cancelButton = this._getCancelButtonConfig();
if (cancelButton) {
buttonsConfig.push(cancelButton)
}
const clearButton = this._getClearButtonConfig();
if (clearButton) {
buttonsConfig.push(clearButton)
}
return this._applyButtonsLocation(buttonsConfig)
}
_popupToolbarItemsConfig() {
const {
focusStateEnabled: focusStateEnabled,
applyButtonText: text
} = this.option();
return [{
shortcut: "done",
options: {
text: text,
focusStateEnabled: focusStateEnabled,
onClick: this._applyButtonHandler.bind(this)
}
}]
}
_getCancelButtonConfig() {
const {
focusStateEnabled: focusStateEnabled,
cancelButtonText: text,
showCancelButton: showCancelButton
} = this.option();
return showCancelButton ? {
shortcut: "cancel",
options: {
text: text,
focusStateEnabled: focusStateEnabled
},
onClick: this._cancelButtonHandler.bind(this)
} : null
}
_getClearButtonConfig() {
const {
showClearButton: showClearButton,
clearButtonText: text,
focusStateEnabled: focusStateEnabled
} = this.option();
return showClearButton ? {
shortcut: "clear",
options: {
text: text,
focusStateEnabled: focusStateEnabled
},
onClick: this._resetValue.bind(this)
} : null
}
_applyButtonHandler(args) {
if (args) {
this._saveValueChangeEvent(args.event)
}
this.option("value", this._valueGetter(this._currentSelectedItem()));
super._applyButtonHandler()
}
_cancelButtonHandler() {
this._refreshSelected();
super._cancelButtonHandler()
}
_refreshPopupVisibility() {
const {
opened: opened
} = this.option();
if (opened) {
this._updateListDimensions()
}
}
_dimensionChanged() {
const {
usePopover: usePopover,
dropDownOptions: {
width: dropDownWidth
} = {}
} = this.option();
if (usePopover && !dropDownWidth) {
this.option("dropDownOptions.width", getWidth(this.$element()))
}
this._updateListDimensions()
}
_input() {
return this._$searchBox || super._input()
}
_renderPopupContent() {
super._renderPopupContent();
this._renderSearch()
}
_renderValueChangeEvent() {}
_renderSearch() {
const {
searchEnabled: isSearchEnabled,
searchStartEvent: searchStartEvent
} = this.option();
this._toggleSearchClass(isSearchEnabled);
if (isSearchEnabled) {
this._$searchWrapper = $("<div>").addClass("dx-lookup-search-wrapper");
const $searchWrapper = this._$searchWrapper;
this._$searchBox = $("<div>").addClass("dx-lookup-search").appendTo($searchWrapper);
const $searchBox = this._$searchBox;
const currentDevice = devices.current();
const searchMode = currentDevice.android ? "text" : "search";
let isKeyboardListeningEnabled = false;
const textBoxOptions = {
mode: searchMode,
showClearButton: true,
valueChangeEvent: searchStartEvent,
inputAttr: {
"aria-label": messageLocalization.format("Search")
},
onDisposing: () => {
isKeyboardListeningEnabled = false
},
onFocusIn: () => {
isKeyboardListeningEnabled = true
},
onFocusOut: () => {
var _this$_list9;
isKeyboardListeningEnabled = false;
null === (_this$_list9 = this._list) || void 0 === _this$_list9 || _this$_list9.option("focusedElement", null)
},
onKeyboardHandled: opts => {
if (isKeyboardListeningEnabled) {
var _this$_list0;
null === (_this$_list0 = this._list) || void 0 === _this$_list0 || _this$_list0._keyboardHandler(opts)
}
},
onValueChanged: () => {
this._searchHandler()
}
};
this._searchBox = this._createComponent($searchBox, TextBox, textBoxOptions);
this._registerSearchKeyHandlers();
$searchWrapper.insertBefore(this._$list);
this._setSearchPlaceholder()
}
}
_filterDataSource(searchValue) {
if (this._list && !this._list._dataSource && this._isMinSearchLengthExceeded()) {
var _this$_list1;
null === (_this$_list1 = this._list) || void 0 === _this$_list1 || _this$_list1._scrollView.startLoading()
}
super._filterDataSource(searchValue)
}
_dataSourceFiltered(searchValue) {
var _this$_list10;
super._dataSourceFiltered(searchValue);
null === (_this$_list10 = this._list) || void 0 === _this$_list10 || _this$_list10._scrollView.finishLoading()
}
_updateActiveDescendant() {
super._updateActiveDescendant();
if (!this._$searchBox) {
return
}
const $input = this._$searchBox.find("input");
super._updateActiveDescendant($input)
}
_removeSearch() {
var _this$_$searchWrapper, _this$_$searchBox;
null === (_this$_$searchWrapper = this._$searchWrapper) || void 0 === _this$_$searchWrapper || _this$_$searchWrapper.remove();
delete this._$searchWrapper;
null === (_this$_$searchBox = this._$searchBox) || void 0 === _this$_$searchBox || _this$_$searchBox.remove();
delete this._$searchBox;
delete this._searchBox
}
_selectListItemHandler(e) {
var _this$_list11;
const {
focusedElement: focusedElement
} = (null === (_this$_list11 = this._list) || void 0 === _this$_list11 ? void 0 : _this$_list11.option()) ?? {};
const $itemElement = $(focusedElement);
if (!$itemElement.length) {
return
}
e.preventDefault();
e.target = $itemElement.get(0);
this._saveValueChangeEvent(e);
this._selectListItem(void 0, $itemElement)
}
_registerSearchKeyHandlers() {
var _this$_searchBox3, _this$_searchBox4, _this$_searchBox5, _this$_searchBox6;
null === (_this$_searchBox3 = this._searchBox) || void 0 === _this$_searchBox3 || _this$_searchBox3.registerKeyHandler("enter", this._selectListItemHandler.bind(this));
null === (_this$_searchBox4 = this._searchBox) || void 0 === _this$_searchBox4 || _this$_searchBox4.registerKeyHandler("space", this._selectListItemHandler.bind(this));
null === (_this$_searchBox5 = this._searchBox) || void 0 === _this$_searchBox5 || _this$_searchBox5.registerKeyHandler("end", noop);
null === (_this$_searchBox6 = this._searchBox) || void 0 === _this$_searchBox6 || _this$_searchBox6.registerKeyHandler("home", noop)
}
_toggleSearchClass(isSearchEnabled) {
if (this._popup) {
var _this$_popup$$wrapper;
null === (_this$_popup$$wrapper = this._popup.$wrapper()) || void 0 === _this$_popup$$wrapper || _this$_popup$$wrapper.toggleClass("dx-lookup-popup-search", isSearchEnabled)
}
}
_setSearchPlaceholder() {
var _this$_searchBox7;
if (!this._$searchBox) {
return
}
const {
minSearchLength: minSearchLength,
searchPlaceholder: searchPlaceholder
} = this.option();
let placeholder = searchPlaceholder;
if (minSearchLength && placeholder === messageLocalization.format("Search")) {
placeholder = messageLocalization.getFormatter("dxLookup-searchPlaceholder")(minSearchLength)
}
null === (_this$_searchBox7 = this._searchBox) || void 0 === _this$_searchBox7 || _this$_searchBox7.option("placeholder", placeholder)
}
_setAriaTargetForList() {}
_listConfig() {
const {
searchEnabled: searchEnabled,
grouped: grouped,
pullRefreshEnabled: pullRefreshEnabled,
useNativeScrolling: useNativeScrolling,
pullingDownText: pullingDownText,
pulledDownText: pulledDownText,
refreshingText: refreshingText,
pageLoadingText: pageLoadingText,
pageLoadMode: pageLoadMode,
nextButtonText: nextButtonText
} = this.option();
return Object.assign({}, super._listConfig(), {
tabIndex: searchEnabled ? -1 : 0,
grouped: grouped,
groupTemplate: this._getTemplateByOption("groupTemplate"),
pullRefreshEnabled: pullRefreshEnabled,
useNativeScrolling: useNativeScrolling,
pullingDownText: pullingDownText,
pulledDownText: pulledDownText,
refreshingText: refreshingText,
pageLoadingText: pageLoadingText,
onScroll: this._scrollHandler.bind(this),
onPullRefresh: this._pullRefreshHandler.bind(this),
onPageLoading: this._pageLoadingHandler.bind(this),
pageLoadMode: pageLoadMode,
nextButtonText: nextButtonText,
indicateLoading: searchEnabled
})
}
_listContentReadyHandler() {
super._listContentReadyHandler();
this._refreshSelected()
}
_runWithoutCloseOnScroll(callback) {
var _this$_popup8;
const {
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
} = this.option();
const {
hideOnParentScroll: hideOnParentScroll
} = (null === (_this$_popup8 = this._popup) || void 0 === _this$_popup8 ? void 0 : _this$_popup8.option()) ?? {};
if (!_scrollToSelectedItemEnabled) {
callback()
} else {
var _this$_popup9;
null === (_this$_popup9 = this._popup) || void 0 === _this$_popup9 || _this$_popup9.option("hideOnParentScroll", false);
callback();
this._hideOnParentScrollTimer = setTimeout(() => {
var _this$_popup0;
null === (_this$_popup0 = this._popup) || void 0 === _this$_popup0 || _this$_popup0.option("hideOnParentScroll", hideOnParentScroll)
})
}
}
_setFocusPolicy() {
const {
focusStateEnabled: focusStateEnabled,
searchEnabled: searchEnabled
} = this.option();
if (!focusStateEnabled) {
return
}
this._runWithoutCloseOnScroll(() => {
if (searchEnabled) {
var _this$_searchBox8;
null === (_this$_searchBox8 = this._searchBox) || void 0 === _this$_searchBox8 || _this$_searchBox8.focus()
} else {
var _this$_list12;
null === (_this$_list12 = this._list) || void 0 === _this$_list12 || _this$_list12.focus()
}
})
}
_focusTarget() {
return this._$field
}
_keyboardEventBindingTarget() {
return this._$field
}
_listItemClickHandler(e) {
var _e$event;
if (!e) {
return
}
this._saveValueChangeEvent(e.event);
this._selectListItem(e.itemData, null === (_e$event = e.event) || void 0 === _e$event ? void 0 : _e$event.currentTarget)
}
_selectListItem(itemData, target) {
if (target) {
var _this$_list13;
null === (_this$_list13 = this._list) || void 0 === _this$_list13 || _this$_list13.selectItem(target)
}
const {
applyValueMode: applyValueMode
} = this.option();
if ("instantly" === applyValueMode) {
this._applyButtonHandler()
}
}
_currentSelectedItem() {
var _this$_list14;
const {
grouped: grouped
} = this.option();
const {
selectedItems: [firstSelectedItem] = []
} = (null === (_this$_list14 = this._list) || void 0 === _this$_list14 ? void 0 : _this$_list14.option()) ?? {};
return grouped ? null === firstSelectedItem || void 0 === firstSelectedItem ? void 0 : firstSelectedItem.items[0] : firstSelectedItem
}
_resetValue(e) {
this._saveValueChangeEvent(e.event);
this.option("value", null);
this.option("opened", false)
}
_searchValue() {
var _this$_searchBox9;
const {
searchEnabled: searchEnabled
} = this.option();
const {
value: searchBoxValue
} = (null === (_this$_searchBox9 = this._searchBox) || void 0 === _this$_searchBox9 ? void 0 : _this$_searchBox9.option()) ?? {};
return searchEnabled && this._searchBox ? searchBoxValue : ""
}
_renderInputValue() {
let arg = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
return super._renderInputValue(arg).always(() => {
this._refreshSelected()
})
}
_renderPlaceholder() {
if (0 === this.$element().find(".dx-texteditor-input").length) {
return
}
super._renderPlaceholder()
}
_clean() {
this._$fieldWrapper.remove();
if (this._hideOnParentScrollTimer) {
clearTimeout(this._hideOnParentScrollTimer)
}
this._hideOnParentScrollTimer = null;
this._$searchBox = null;
super._clean()
}
_optionChanged(args) {
var _this$_searchBox0;
const {
name: name,
fullName: fullName,
value: value
} = args;
switch (name) {
case "dataSource":
super._optionChanged(args);
this._renderField();
break;
case "searchEnabled":
if (this._popup) {
this._removeSearch();
this._renderSearch()
}
this._setListOption("tabIndex", value ? -1 : 0);
break;
case "searchPlaceholder":
this._setSearchPlaceholder();
break;
case "minSearchLength":
this._setSearchPlaceholder();
super._optionChanged(args);
break;
case "inputAttr":
this._applyInputAttributes(value);
break;
case "usePopover":
case "placeholder":
this._invalidate();
break;
case "focusStateEnabled":
this._setPopupOption("toolbarItems", this._getPopupToolbarItems());
super._optionChanged(args);
break;
case "clearButtonText":
case "showClearButton":
case "showCancelButton":
this._setPopupOption("toolbarItems", this._getPopupToolbarItems());
break;
case "applyValueMode":
default:
super._optionChanged(args);
break;
case "onPageLoading":
this._initPageLoadingAction();
break;
case "onPullRefresh":
this._initPullRefreshAction();
break;
case "pullRefreshEnabled":
case "useNativeScrolling":
case "pullingDownText":
case "pulledDownText":
case "refreshingText":
case "pageLoadingText":
case "nextButtonText":
case "grouped":
case "groupTemplate":
this._setListOption(name);
break;
case "searchStartEvent":
null === (_this$_searchBox0 = this._searchBox) || void 0 === _this$_searchBox0 || _this$_searchBox0.option("valueChangeEvent", value);
break;
case "onScroll":
this._initScrollAction();
break;
case "pageLoadMode": {
const {
pageLoadMode: pageLoadMode
} = this.option();
this._setListOption("pageLoadMode", pageLoadMode);
break
}
case "cleanSearchOnOpening":
case "_scrollToSelectedItemEnabled":
break;
case "dropDownOptions":
switch (fullName) {
case "dropDownOptions.width":
case "dropDownOptions.height": {
const optionArgs = Object.assign({}, args, {
value: "auto" === value ? this.initialOption("dropDownOptions")[getFieldName(fullName)] : value
});
this._popupOptionChanged(optionArgs);
this._innerWidgetOptionChanged(this._popup, optionArgs);
break
}
default:
super._optionChanged(args)
}
break;
case "dropDownCentered": {
const {
_scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
} = this.option();
if (_scrollToSelectedItemEnabled) {
this.option("dropDownOptions.position", void 0);
this._renderPopup()
}
break
}
}
}
focus() {
const {
opened: opened
} = this.option();
if (opened) {
this._setFocusPolicy();
return
}
eventsEngine.trigger(this._focusTarget(), "focus")
}
field() {
return this._$field
}
}
registerComponent("dxLookup", Lookup);
export default Lookup;