lookup.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /**
  2. * DevExtreme (ui/lookup.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var $ = require("../core/renderer");
  11. var eventsEngine = require("../events/core/events_engine");
  12. var window = require("../core/utils/window").getWindow();
  13. var support = require("../core/utils/support");
  14. var commonUtils = require("../core/utils/common");
  15. var domUtils = require("../core/utils/dom");
  16. var each = require("../core/utils/iterator").each;
  17. var extend = require("../core/utils/extend").extend;
  18. var inkRipple = require("./widget/utils.ink_ripple");
  19. var messageLocalization = require("../localization/message");
  20. var devices = require("../core/devices");
  21. var registerComponent = require("../core/component_registrator");
  22. var eventUtils = require("../events/utils");
  23. var DropDownList = require("./drop_down_editor/ui.drop_down_list");
  24. var themes = require("./themes");
  25. var clickEvent = require("../events/click");
  26. var Popover = require("./popover");
  27. var TextBox = require("./text_box");
  28. var ChildDefaultTemplate = require("./widget/child_default_template");
  29. var translator = require("../animation/translator");
  30. var LOOKUP_CLASS = "dx-lookup";
  31. var LOOKUP_SEARCH_CLASS = "dx-lookup-search";
  32. var LOOKUP_SEARCH_WRAPPER_CLASS = "dx-lookup-search-wrapper";
  33. var LOOKUP_FIELD_CLASS = "dx-lookup-field";
  34. var LOOKUP_ARROW_CLASS = "dx-lookup-arrow";
  35. var LOOKUP_FIELD_WRAPPER_CLASS = "dx-lookup-field-wrapper";
  36. var LOOKUP_POPUP_CLASS = "dx-lookup-popup";
  37. var LOOKUP_POPUP_WRAPPER_CLASS = "dx-lookup-popup-wrapper";
  38. var LOOKUP_POPUP_SEARCH_CLASS = "dx-lookup-popup-search";
  39. var LOOKUP_POPOVER_MODE = "dx-lookup-popover-mode";
  40. var LOOKUP_EMPTY_CLASS = "dx-lookup-empty";
  41. var LOOKUP_POPOVER_FLIP_VERTICAL_CLASS = "dx-popover-flipped-vertical";
  42. var TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input";
  43. var POPUP_OPTION_MAP = {
  44. popupWidth: "width",
  45. popupHeight: "height"
  46. };
  47. var LIST_ITEM_SELECTED_CLASS = "dx-list-item-selected";
  48. var MATERIAL_LOOKUP_LIST_ITEMS_COUNT = 4;
  49. var MATERIAL_LOOKUP_LIST_PADDING = 8;
  50. var Lookup = DropDownList.inherit({
  51. _supportedKeys: function() {
  52. return extend(this.callBase(), {
  53. space: function(e) {
  54. e.preventDefault();
  55. this._validatedOpening()
  56. },
  57. enter: function() {
  58. this._validatedOpening()
  59. }
  60. })
  61. },
  62. _getDefaultOptions: function() {
  63. return extend(this.callBase(), {
  64. title: "",
  65. titleTemplate: "title",
  66. onTitleRendered: null,
  67. placeholder: messageLocalization.format("Select"),
  68. searchPlaceholder: messageLocalization.format("Search"),
  69. searchEnabled: true,
  70. cleanSearchOnOpening: true,
  71. fullScreen: false,
  72. showCancelButton: true,
  73. showClearButton: false,
  74. clearButtonText: messageLocalization.format("Clear"),
  75. applyButtonText: messageLocalization.format("OK"),
  76. popupWidth: function() {
  77. return .8 * $(window).width()
  78. },
  79. popupHeight: function() {
  80. return .8 * $(window).height()
  81. },
  82. shading: true,
  83. closeOnOutsideClick: false,
  84. position: void 0,
  85. animation: {},
  86. pullRefreshEnabled: false,
  87. useNativeScrolling: true,
  88. pullingDownText: messageLocalization.format("dxList-pullingDownText"),
  89. pulledDownText: messageLocalization.format("dxList-pulledDownText"),
  90. refreshingText: messageLocalization.format("dxList-refreshingText"),
  91. pageLoadingText: messageLocalization.format("dxList-pageLoadingText"),
  92. onScroll: null,
  93. onPullRefresh: null,
  94. onPageLoading: null,
  95. pageLoadMode: "scrollBottom",
  96. nextButtonText: messageLocalization.format("dxList-nextButtonText"),
  97. grouped: false,
  98. groupTemplate: "group",
  99. usePopover: false,
  100. showDropDownButton: false,
  101. showPopupTitle: true,
  102. focusStateEnabled: false,
  103. _scrollToSelectedItemEnabled: false,
  104. useHiddenSubmitElement: true
  105. })
  106. },
  107. _defaultOptionsRules: function() {
  108. var themeName = themes.current();
  109. return this.callBase().concat([{
  110. device: function() {
  111. return !support.nativeScrolling
  112. },
  113. options: {
  114. useNativeScrolling: false
  115. }
  116. }, {
  117. device: function(_device) {
  118. return !devices.isSimulator() && "generic" === devices.real().platform && "generic" === _device.platform
  119. },
  120. options: {
  121. usePopover: true,
  122. popupHeight: "auto"
  123. }
  124. }, {
  125. device: function(_device2) {
  126. return "win" === _device2.platform && _device2.phone && _device2.version && 8 === _device2.version[0]
  127. },
  128. options: {
  129. showCancelButton: false,
  130. fullScreen: true
  131. }
  132. }, {
  133. device: function(_device3) {
  134. return "win" === _device3.platform && !_device3.phone && _device3.version && 8 === _device3.version[0]
  135. },
  136. options: {
  137. popupWidth: function() {
  138. return $(window).width()
  139. }
  140. }
  141. }, {
  142. device: {
  143. platform: "ios",
  144. phone: true
  145. },
  146. options: {
  147. fullScreen: true
  148. }
  149. }, {
  150. device: {
  151. platform: "ios",
  152. tablet: true
  153. },
  154. options: {
  155. popupWidth: function() {
  156. return .4 * Math.min($(window).width(), $(window).height())
  157. },
  158. popupHeight: "auto",
  159. usePopover: true,
  160. useInkRipple: false
  161. }
  162. }, {
  163. device: function() {
  164. return "desktop" === devices.real().deviceType && !devices.isSimulator()
  165. },
  166. options: {
  167. focusStateEnabled: true
  168. }
  169. }, {
  170. device: function() {
  171. return themes.isMaterial(themeName)
  172. },
  173. options: {
  174. usePopover: false,
  175. closeOnOutsideClick: true,
  176. popupWidth: function() {
  177. return $(this.element()).outerWidth()
  178. }.bind(this),
  179. popupHeight: function() {
  180. return this._getPopupHeight(MATERIAL_LOOKUP_LIST_ITEMS_COUNT)
  181. }.bind(this),
  182. searchEnabled: false,
  183. showCancelButton: false,
  184. showPopupTitle: false,
  185. position: {
  186. my: "left top",
  187. at: "left top",
  188. of: this.element()
  189. },
  190. _scrollToSelectedItemEnabled: true
  191. }
  192. }])
  193. },
  194. _init: function() {
  195. this.callBase();
  196. this._createScrollAction()
  197. },
  198. _createScrollAction: function() {
  199. this._scrollAction = this._createActionByOption("onScroll")
  200. },
  201. _scrollHandler: function(e) {
  202. this._scrollAction(e)
  203. },
  204. _initTemplates: function() {
  205. this.callBase();
  206. this._defaultTemplates.group = new ChildDefaultTemplate("group", this);
  207. this._defaultTemplates.title = new ChildDefaultTemplate("title", this)
  208. },
  209. _initMarkup: function() {
  210. this.$element().addClass(LOOKUP_CLASS).toggleClass(LOOKUP_POPOVER_MODE, this.option("usePopover"));
  211. this.callBase()
  212. },
  213. _inputWrapper: function() {
  214. return this.$element().find("." + LOOKUP_FIELD_WRAPPER_CLASS)
  215. },
  216. _dataSourceOptions: function() {
  217. return extend(this.callBase(), {
  218. paginate: true
  219. })
  220. },
  221. _fireContentReadyAction: commonUtils.noop,
  222. _popupWrapperClass: function() {
  223. return ""
  224. },
  225. _renderInput: function() {
  226. var fieldClickAction = this._createAction(function() {
  227. this._toggleOpenState()
  228. }.bind(this));
  229. this._$field = $("<div>").addClass(LOOKUP_FIELD_CLASS);
  230. eventsEngine.on(this._$field, eventUtils.addNamespace(clickEvent.name, this.NAME), function(e) {
  231. fieldClickAction({
  232. event: e
  233. })
  234. });
  235. var $arrow = $("<div>").addClass(LOOKUP_ARROW_CLASS);
  236. this._$fieldWrapper = $("<div>").addClass(LOOKUP_FIELD_WRAPPER_CLASS).append(this._$field).append($arrow).appendTo(this.$element());
  237. this.option("useInkRipple") && this._renderInkRipple()
  238. },
  239. _renderInkRipple: function() {
  240. this._inkRipple = inkRipple.render()
  241. },
  242. _toggleOpenState: function() {
  243. this.callBase();
  244. if (!this.option("fullScreen") && this.option("_scrollToSelectedItemEnabled")) {
  245. this._setPopupPosition()
  246. }
  247. },
  248. _toggleActiveState: function($element, value, e) {
  249. this.callBase.apply(this, arguments);
  250. if (!this._inkRipple) {
  251. return
  252. }
  253. var config = {
  254. element: this._inputWrapper(),
  255. event: e
  256. };
  257. if (value) {
  258. this._inkRipple.showWave(config)
  259. } else {
  260. this._inkRipple.hideWave(config)
  261. }
  262. },
  263. _renderField: function() {
  264. var fieldTemplate = this._getTemplateByOption("fieldTemplate");
  265. if (fieldTemplate && this.option("fieldTemplate")) {
  266. this._renderFieldTemplate(fieldTemplate);
  267. return
  268. }
  269. this._updateField(this.option("displayValue") || this.option("placeholder"));
  270. this.$element().toggleClass(LOOKUP_EMPTY_CLASS, !this.option("selectedItem"))
  271. },
  272. _renderDisplayText: function(text) {
  273. if (this._input().length) {
  274. this.callBase(text)
  275. } else {
  276. this._updateField(text)
  277. }
  278. },
  279. _updateField: function(text) {
  280. this._$field.text(text)
  281. },
  282. _renderFieldTemplate: function(template) {
  283. this._$field.empty();
  284. var data = this._fieldRenderData();
  285. template.render({
  286. model: data,
  287. container: domUtils.getPublicElement(this._$field)
  288. })
  289. },
  290. _fieldRenderData: function() {
  291. return this.option("selectedItem")
  292. },
  293. _popupShowingHandler: function() {
  294. this.callBase.apply(this, arguments);
  295. if (this.option("cleanSearchOnOpening")) {
  296. if (this.option("searchEnabled") && this._searchBox.option("value")) {
  297. this._searchBox.option("value", "");
  298. this._searchCanceled()
  299. }
  300. this._list && this._list.option("focusedElement", null)
  301. }
  302. if (this.option("fullScreen") && this.option("_scrollToSelectedItemEnabled")) {
  303. this._popup.option("position").of = $(window)
  304. }
  305. },
  306. _scrollToSelectedItem: function() {
  307. var selectedIndex = this._list.option("selectedIndex");
  308. var listItems = this._list.option("items");
  309. var itemsCount = listItems.length;
  310. if (0 !== itemsCount) {
  311. if (this._list.option("grouped")) {
  312. this._list.scrollToItem({
  313. group: itemsCount - 1,
  314. item: listItems[itemsCount - 1].items.length - 1
  315. })
  316. } else {
  317. this._list.scrollToItem(itemsCount - 1)
  318. }
  319. this._list.scrollToItem(selectedIndex)
  320. }
  321. },
  322. _setPopupPosition: function() {
  323. var selectedIndex = this._list.option("selectedIndex");
  324. var flipped = this._popup._$wrapper.hasClass(LOOKUP_POPOVER_FLIP_VERTICAL_CLASS);
  325. if (selectedIndex === -1 || flipped) {
  326. return
  327. }
  328. var selectedListItem = $(this._list.element()).find("." + LIST_ITEM_SELECTED_CLASS);
  329. if (selectedListItem.offset().top < 0) {
  330. this._scrollToSelectedItem()
  331. }
  332. var differenceOfHeights = (selectedListItem.height() - $(this.element()).height()) / 2;
  333. var popupContentParent = $(this._popup.content()).parent();
  334. var differenceOfOffsets = selectedListItem.offset().top - popupContentParent.offset().top;
  335. var lookupTop = $(this.element()).offset().top;
  336. var popupOffsetY = differenceOfHeights;
  337. if (lookupTop > differenceOfOffsets) {
  338. popupOffsetY += differenceOfOffsets
  339. } else {
  340. this._scrollToSelectedItem()
  341. }
  342. var position = translator.locate(popupContentParent);
  343. translator.move(popupContentParent, {
  344. top: position.top - popupOffsetY
  345. })
  346. },
  347. _getPopupHeight: function(listItemsCount) {
  348. return this._list && this._list.itemElements() ? this._list.itemElements().height() * listItemsCount + 2 * MATERIAL_LOOKUP_LIST_PADDING : "auto"
  349. },
  350. _renderPopup: function() {
  351. if (this.option("usePopover") && !this.option("fullScreen")) {
  352. this._renderPopover()
  353. } else {
  354. this.callBase()
  355. }
  356. this._$popup.addClass(LOOKUP_POPUP_CLASS);
  357. this._popup._wrapper().addClass(LOOKUP_POPUP_WRAPPER_CLASS)
  358. },
  359. _popupOptionMap: function(optionName) {
  360. return POPUP_OPTION_MAP[optionName] || optionName
  361. },
  362. _renderPopover: function() {
  363. this._popup = this._createComponent(this._$popup, Popover, extend(this._popupConfig(), {
  364. showEvent: null,
  365. hideEvent: null,
  366. target: this.$element(),
  367. fullScreen: false,
  368. shading: false,
  369. closeOnTargetScroll: true,
  370. width: this._isInitialOptionValue("popupWidth") ? function() {
  371. return this.$element().outerWidth()
  372. }.bind(this) : this._popupConfig().width
  373. }));
  374. this._popup.on({
  375. showing: this._popupShowingHandler.bind(this),
  376. shown: this._popupShownHandler.bind(this),
  377. hiding: this._popupHidingHandler.bind(this),
  378. hidden: this._popupHiddenHandler.bind(this)
  379. });
  380. this._setPopupContentId(this._popup.$content());
  381. this._popup.option("onContentReady", this._contentReadyHandler.bind(this));
  382. this._contentReadyHandler()
  383. },
  384. _popupHidingHandler: function() {
  385. this.callBase();
  386. this.option("focusStateEnabled") && this.focus()
  387. },
  388. _popupHiddenHandler: function() {
  389. this.callBase();
  390. if (this.option("_scrollToSelectedItemEnabled")) {
  391. translator.resetPosition($(this._popup.content()).parent())
  392. }
  393. },
  394. _preventFocusOnPopup: commonUtils.noop,
  395. _popupConfig: function() {
  396. var result = extend(this.callBase(), {
  397. showTitle: this.option("showPopupTitle"),
  398. title: this.option("title"),
  399. titleTemplate: this._getTemplateByOption("titleTemplate"),
  400. onTitleRendered: this.option("onTitleRendered"),
  401. toolbarItems: this._getPopupToolbarItems(),
  402. fullScreen: this.option("fullScreen"),
  403. shading: this.option("shading"),
  404. closeOnTargetScroll: false,
  405. closeOnOutsideClick: this.option("closeOnOutsideClick"),
  406. onPositioned: null
  407. });
  408. delete result.animation;
  409. delete result.position;
  410. result.maxHeight = function() {
  411. return $(window).height()
  412. };
  413. each(["position", "animation", "popupWidth", "popupHeight"], function(_, optionName) {
  414. if (void 0 !== this.option(optionName)) {
  415. result[this._popupOptionMap(optionName)] = this.option(optionName)
  416. }
  417. }.bind(this));
  418. return result
  419. },
  420. _getPopupToolbarItems: function() {
  421. var buttonsConfig = "useButtons" === this.option("applyValueMode") ? this._popupToolbarItemsConfig() : [];
  422. var cancelButton = this._getCancelButtonConfig();
  423. if (cancelButton) {
  424. buttonsConfig.push(cancelButton)
  425. }
  426. var clearButton = this._getClearButtonConfig();
  427. if (clearButton) {
  428. buttonsConfig.push(clearButton)
  429. }
  430. return this._applyButtonsLocation(buttonsConfig)
  431. },
  432. _popupToolbarItemsConfig: function() {
  433. return [{
  434. shortcut: "done",
  435. options: {
  436. onClick: this._applyButtonHandler.bind(this),
  437. text: this.option("applyButtonText")
  438. }
  439. }]
  440. },
  441. _getCancelButtonConfig: function() {
  442. return this.option("showCancelButton") ? {
  443. shortcut: "cancel",
  444. onClick: this._cancelButtonHandler.bind(this),
  445. options: {
  446. onInitialized: function(e) {
  447. e.component.registerKeyHandler("escape", this.close.bind(this))
  448. }.bind(this),
  449. text: this.option("cancelButtonText")
  450. }
  451. } : null
  452. },
  453. _getClearButtonConfig: function() {
  454. return this.option("showClearButton") ? {
  455. shortcut: "clear",
  456. onClick: this._resetValue.bind(this),
  457. options: {
  458. text: this.option("clearButtonText")
  459. }
  460. } : null
  461. },
  462. _applyButtonHandler: function() {
  463. this.option("value", this._valueGetter(this._currentSelectedItem()));
  464. this.callBase()
  465. },
  466. _cancelButtonHandler: function() {
  467. this._refreshSelected();
  468. this.callBase()
  469. },
  470. _refreshPopupVisibility: function() {
  471. if (this.option("opened")) {
  472. this._updatePopupHeight()
  473. }
  474. },
  475. _dimensionChanged: function() {
  476. if (this.option("usePopover") && !this.option("popupWidth")) {
  477. this.option("popupWidth", this.$element().width())
  478. }
  479. this.callBase()
  480. },
  481. _updatePopupDimensions: function() {
  482. this._updatePopupHeight()
  483. },
  484. _input: function() {
  485. return this._$searchBox || this.callBase()
  486. },
  487. _renderPopupContent: function() {
  488. this.callBase();
  489. this._renderSearch()
  490. },
  491. _attachSearchChildProcessor: function(searchComponent) {
  492. this._listKeyboardProcessor = this._listKeyboardProcessor || searchComponent._keyboardProcessor.attachChildProcessor();
  493. this._setListOption("_keyboardProcessor", this._listKeyboardProcessor)
  494. },
  495. _detachSearchChildProcessor: function() {
  496. this._setListOption("_keyboardProcessor", null)
  497. },
  498. _renderSearch: function() {
  499. var isSearchEnabled = this.option("searchEnabled");
  500. this._toggleSearchClass(isSearchEnabled);
  501. if (isSearchEnabled) {
  502. var $searchWrapper = this._$searchWrapper = $("<div>").addClass(LOOKUP_SEARCH_WRAPPER_CLASS);
  503. var $searchBox = this._$searchBox = $("<div>").addClass(LOOKUP_SEARCH_CLASS).appendTo($searchWrapper);
  504. var currentDevice = devices.current();
  505. var searchMode = currentDevice.android && currentDevice.version[0] >= 5 ? "text" : "search";
  506. this._searchBox = this._createComponent($searchBox, TextBox, {
  507. onDisposing: function() {
  508. this._detachSearchChildProcessor()
  509. }.bind(this),
  510. onFocusIn: this._searchFocusHandler.bind(this),
  511. onFocusOut: this._searchBlurHandler.bind(this),
  512. mode: searchMode,
  513. showClearButton: true,
  514. valueChangeEvent: this.option("valueChangeEvent"),
  515. onValueChanged: this._searchHandler.bind(this)
  516. });
  517. this._registerSearchKeyHandlers();
  518. $searchWrapper.insertBefore(this._$list);
  519. this._setSearchPlaceholder()
  520. }
  521. },
  522. _searchFocusHandler: function(e) {
  523. this._attachSearchChildProcessor(e.component)
  524. },
  525. _searchBlurHandler: function() {
  526. this._detachSearchChildProcessor()
  527. },
  528. _removeSearch: function() {
  529. this._$searchWrapper && this._$searchWrapper.remove();
  530. delete this._$searchWrapper;
  531. this._$searchBox && this._$searchBox.remove();
  532. delete this._$searchBox;
  533. delete this._searchBox
  534. },
  535. _selectListItemHandler: function(e) {
  536. var $itemElement = $(this._list.option("focusedElement"));
  537. if (!$itemElement.length) {
  538. return
  539. }
  540. e.preventDefault();
  541. this._selectListItem(e.itemData, $itemElement)
  542. },
  543. _registerSearchKeyHandlers: function() {
  544. this._searchBox.registerKeyHandler("escape", this.close.bind(this));
  545. this._searchBox.registerKeyHandler("enter", this._selectListItemHandler.bind(this));
  546. this._searchBox.registerKeyHandler("space", this._selectListItemHandler.bind(this));
  547. this._searchBox.registerKeyHandler("end", commonUtils.noop);
  548. this._searchBox.registerKeyHandler("home", commonUtils.noop)
  549. },
  550. _toggleSearchClass: function(isSearchEnabled) {
  551. if (this._popup) {
  552. this._popup._wrapper().toggleClass(LOOKUP_POPUP_SEARCH_CLASS, isSearchEnabled)
  553. }
  554. },
  555. _setSearchPlaceholder: function() {
  556. if (!this._$searchBox) {
  557. return
  558. }
  559. var minSearchLength = this.option("minSearchLength");
  560. var placeholder = this.option("searchPlaceholder");
  561. if (minSearchLength && placeholder === messageLocalization.format("Search")) {
  562. placeholder = messageLocalization.getFormatter("dxLookup-searchPlaceholder")(minSearchLength)
  563. }
  564. this._searchBox.option("placeholder", placeholder)
  565. },
  566. _setAriaTargetForList: commonUtils.noop,
  567. _renderList: function() {
  568. this.callBase();
  569. this._list.registerKeyHandler("escape", function() {
  570. this.close()
  571. }.bind(this))
  572. },
  573. _listConfig: function() {
  574. return extend(this.callBase(), {
  575. tabIndex: 0,
  576. grouped: this.option("grouped"),
  577. groupTemplate: this._getTemplateByOption("groupTemplate"),
  578. pullRefreshEnabled: this.option("pullRefreshEnabled"),
  579. useNativeScrolling: this.option("useNativeScrolling"),
  580. pullingDownText: this.option("pullingDownText"),
  581. pulledDownText: this.option("pulledDownText"),
  582. refreshingText: this.option("refreshingText"),
  583. pageLoadingText: this.option("pageLoadingText"),
  584. onScroll: this._scrollHandler.bind(this),
  585. onPullRefresh: this.option("onPullRefresh"),
  586. onPageLoading: this.option("onPageLoading"),
  587. pageLoadMode: this.option("pageLoadMode"),
  588. nextButtonText: this.option("nextButtonText"),
  589. _keyboardProcessor: this._listKeyboardProcessor,
  590. indicateLoading: this.option("searchEnabled"),
  591. onSelectionChanged: this._getSelectionChangedHandler()
  592. })
  593. },
  594. _getSelectionChangedHandler: function() {
  595. return this.option("showSelectionControls") ? this._selectionChangeHandler.bind(this) : commonUtils.noop
  596. },
  597. _listContentReadyHandler: function() {
  598. this.callBase.apply(this, arguments);
  599. this._refreshSelected()
  600. },
  601. _setFocusPolicy: function() {
  602. if (!this.option("focusStateEnabled")) {
  603. return
  604. }
  605. if (this.option("searchEnabled")) {
  606. this._searchBox.focus()
  607. } else {
  608. eventsEngine.trigger(this._$list, "focus")
  609. }
  610. },
  611. _attachChildKeyboardEvents: commonUtils.noop,
  612. _focusTarget: function() {
  613. return this._$field
  614. },
  615. _keyboardEventBindingTarget: function() {
  616. return this._$field
  617. },
  618. _listItemClickHandler: function(e) {
  619. this._saveValueChangeEvent(e.event);
  620. this._selectListItem(e.itemData, e.event.currentTarget)
  621. },
  622. _selectListItem: function(itemData, target) {
  623. this._list.selectItem(target);
  624. if ("instantly" === this.option("applyValueMode")) {
  625. this._applyButtonHandler()
  626. }
  627. },
  628. _currentSelectedItem: function() {
  629. return this.option("grouped") ? this._list.option("selectedItems[0]").items[0] : this._list.option("selectedItems[0]")
  630. },
  631. _resetValue: function(e) {
  632. this._saveValueChangeEvent(e.event);
  633. this.option("value", null);
  634. this.option("opened", false)
  635. },
  636. _searchValue: function() {
  637. return this.option("searchEnabled") && this._searchBox ? this._searchBox.option("value") : ""
  638. },
  639. _renderInputValue: function() {
  640. return this.callBase().always(function() {
  641. this._refreshSelected()
  642. }.bind(this))
  643. },
  644. _renderPlaceholder: function() {
  645. if (0 === this.$element().find("." + TEXTEDITOR_INPUT_CLASS).length) {
  646. return
  647. }
  648. this.callBase()
  649. },
  650. _clean: function() {
  651. this._$fieldWrapper.remove();
  652. this._$searchBox = null;
  653. delete this._inkRipple;
  654. this.callBase()
  655. },
  656. _optionChanged: function(args) {
  657. var name = args.name;
  658. var value = args.value;
  659. switch (name) {
  660. case "dataSource":
  661. this.callBase.apply(this, arguments);
  662. this._renderField();
  663. break;
  664. case "searchEnabled":
  665. if (this._popup) {
  666. this._removeSearch();
  667. this._renderSearch()
  668. }
  669. break;
  670. case "searchPlaceholder":
  671. this._setSearchPlaceholder();
  672. break;
  673. case "minSearchLength":
  674. this._setSearchPlaceholder();
  675. this.callBase.apply(this, arguments);
  676. break;
  677. case "title":
  678. case "titleTemplate":
  679. case "onTitleRendered":
  680. case "shading":
  681. case "animation":
  682. case "position":
  683. case "closeOnOutsideClick":
  684. this._setPopupOption(name);
  685. break;
  686. case "fullScreen":
  687. case "usePopover":
  688. case "placeholder":
  689. this._invalidate();
  690. break;
  691. case "clearButtonText":
  692. case "showClearButton":
  693. case "showCancelButton":
  694. this._setPopupOption("toolbarItems", this._getPopupToolbarItems());
  695. break;
  696. case "applyValueMode":
  697. this.callBase.apply(this, arguments);
  698. break;
  699. case "popupWidth":
  700. this._setPopupOption("popupWidth", "auto" === value ? this.initialOption("popupWidth") : value);
  701. break;
  702. case "popupHeight":
  703. this._setPopupOption("popupHeight", "auto" === value ? this.initialOption("popupHeight") : value);
  704. break;
  705. case "pullRefreshEnabled":
  706. case "useNativeScrolling":
  707. case "pullingDownText":
  708. case "pulledDownText":
  709. case "refreshingText":
  710. case "pageLoadingText":
  711. case "onPullRefresh":
  712. case "onPageLoading":
  713. case "nextButtonText":
  714. case "grouped":
  715. case "groupTemplate":
  716. this._setListOption(name);
  717. break;
  718. case "onScroll":
  719. this._createScrollAction();
  720. break;
  721. case "pageLoadMode":
  722. this._setListOption("pageLoadMode", this.option("pageLoadMode"));
  723. break;
  724. case "cleanSearchOnOpening":
  725. case "_scrollToSelectedItemEnabled":
  726. break;
  727. default:
  728. this.callBase.apply(this, arguments)
  729. }
  730. },
  731. focus: function() {
  732. this.option("opened") ? this._setFocusPolicy() : eventsEngine.trigger(this._focusTarget(), "focus")
  733. },
  734. field: function() {
  735. return this._$field
  736. }
  737. });
  738. registerComponent("dxLookup", Lookup);
  739. module.exports = Lookup;
  740. module.exports.default = module.exports;