drop_down_button.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /**
  2. * DevExtreme (ui/drop_down_button.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 _renderer = require("../core/renderer");
  11. var _renderer2 = _interopRequireDefault(_renderer);
  12. var _ui = require("./widget/ui.widget");
  13. var _ui2 = _interopRequireDefault(_ui);
  14. var _function_template = require("./widget/function_template");
  15. var _function_template2 = _interopRequireDefault(_function_template);
  16. var _component_registrator = require("../core/component_registrator");
  17. var _component_registrator2 = _interopRequireDefault(_component_registrator);
  18. var _button_group = require("./button_group");
  19. var _button_group2 = _interopRequireDefault(_button_group);
  20. var _popup = require("./popup");
  21. var _popup2 = _interopRequireDefault(_popup);
  22. var _list = require("./list");
  23. var _list2 = _interopRequireDefault(_list);
  24. var _data = require("../core/utils/data");
  25. var _dom = require("../core/utils/dom");
  26. var _dom2 = _interopRequireDefault(_dom);
  27. var _icon = require("../core/utils/icon");
  28. var _data_helper = require("../data_helper");
  29. var _data_helper2 = _interopRequireDefault(_data_helper);
  30. var _data_source = require("../data/data_source/data_source");
  31. var _array_store = require("../data/array_store");
  32. var _array_store2 = _interopRequireDefault(_array_store);
  33. var _deferred = require("../core/utils/deferred");
  34. var _extend = require("../core/utils/extend");
  35. var _type = require("../core/utils/type");
  36. var _common = require("../core/utils/common");
  37. var _guid = require("../core/guid");
  38. var _guid2 = _interopRequireDefault(_guid);
  39. var _message = require("../localization/message");
  40. function _interopRequireDefault(obj) {
  41. return obj && obj.__esModule ? obj : {
  42. "default": obj
  43. }
  44. }
  45. var DROP_DOWN_BUTTON_CLASS = "dx-dropdownbutton";
  46. var DROP_DOWN_BUTTON_CONTENT = "dx-dropdownbutton-content";
  47. var DROP_DOWN_BUTTON_ACTION_CLASS = "dx-dropdownbutton-action";
  48. var DROP_DOWN_BUTTON_TOGGLE_CLASS = "dx-dropdownbutton-toggle";
  49. var DX_BUTTON_CONTENT_CLASS = "dx-button-content";
  50. var DX_ICON_RIGHT_CLASS = "dx-icon-right";
  51. var DROP_DOWN_BUTTON_POPUP_WRAPPER_CLASS = "dx-dropdownbutton-popup-wrapper";
  52. var DropDownButton = _ui2.default.inherit({
  53. _getDefaultOptions: function() {
  54. return (0, _extend.extend)(this.callBase(), {
  55. itemTemplate: "item",
  56. keyExpr: "this",
  57. displayExpr: "this",
  58. selectedItem: null,
  59. selectedItemKey: null,
  60. stylingMode: "outlined",
  61. deferRendering: true,
  62. noDataText: (0, _message.format)("dxCollectionWidget-noDataText"),
  63. useSelectMode: false,
  64. splitButton: false,
  65. showArrowIcon: true,
  66. text: "",
  67. icon: void 0,
  68. onButtonClick: null,
  69. onSelectionChanged: null,
  70. onItemClick: null,
  71. opened: false,
  72. items: null,
  73. dataSource: null,
  74. focusStateEnabled: true,
  75. hoverStateEnabled: true,
  76. dropDownOptions: {},
  77. dropDownContentTemplate: "content",
  78. grouped: false,
  79. groupTemplate: "group",
  80. buttonGroupOptions: {}
  81. })
  82. },
  83. _setOptionsByReference: function() {
  84. this.callBase();
  85. (0, _extend.extend)(this._optionsByReference, {
  86. selectedItem: true
  87. })
  88. },
  89. _init: function() {
  90. this.callBase();
  91. this._createItemClickAction();
  92. this._createActionClickAction();
  93. this._createSelectionChangedAction();
  94. this._compileKeyGetter();
  95. this._compileDisplayGetter();
  96. this._initDataSource();
  97. this._itemsToDataSource();
  98. this._initInnerOptionCache("buttonGroupOptions");
  99. this._initInnerOptionCache("dropDownOptions")
  100. },
  101. _initTemplates: function() {
  102. var _this = this;
  103. this.callBase();
  104. this._defaultTemplates.content = new _function_template2.default(function(options) {
  105. var $popupContent = (0, _renderer2.default)(options.container);
  106. var $listContainer = (0, _renderer2.default)("<div>").appendTo($popupContent);
  107. _this._list = _this._createComponent($listContainer, _list2.default, _this._listOptions());
  108. _this._list.registerKeyHandler("escape", _this._escHandler.bind(_this));
  109. _this._list.registerKeyHandler("tab", _this._escHandler.bind(_this));
  110. _this._list.registerKeyHandler("leftArrow", _this._escHandler.bind(_this));
  111. _this._list.registerKeyHandler("rightArrow", _this._escHandler.bind(_this))
  112. })
  113. },
  114. _itemsToDataSource: function() {
  115. if (!this._dataSource) {
  116. this._dataSource = new _data_source.DataSource({
  117. store: new _array_store2.default(this.option("items")),
  118. pageSize: 0
  119. })
  120. }
  121. },
  122. _compileKeyGetter: function() {
  123. this._keyGetter = (0, _data.compileGetter)(this.option("keyExpr"))
  124. },
  125. _compileDisplayGetter: function() {
  126. this._displayGetter = (0, _data.compileGetter)(this.option("displayExpr"))
  127. },
  128. _initMarkup: function() {
  129. this.callBase();
  130. this.$element().addClass(DROP_DOWN_BUTTON_CLASS);
  131. this._renderButtonGroup();
  132. this._loadSelectedItem().done(this._updateActionButton.bind(this));
  133. if (!this.option("deferRendering") || this.option("opened")) {
  134. this._renderPopup()
  135. }
  136. },
  137. _loadSelectedItem: function() {
  138. var d = new _deferred.Deferred;
  139. if (this._list) {
  140. var cachedResult = this.option("useSelectMode") ? this._list.option("selectedItem") : this._lastSelectedItemData;
  141. return d.resolve(cachedResult)
  142. }
  143. this._lastSelectedItemData = void 0;
  144. var selectedItemKey = this.option("selectedItemKey");
  145. this._loadSingle(this.option("keyExpr"), selectedItemKey).done(d.resolve).fail(function() {
  146. d.resolve(null)
  147. });
  148. return d.promise()
  149. },
  150. _createActionClickAction: function() {
  151. this._actionClickAction = this._createActionByOption("onButtonClick")
  152. },
  153. _createSelectionChangedAction: function() {
  154. this._selectionChangedAction = this._createActionByOption("onSelectionChanged")
  155. },
  156. _createItemClickAction: function() {
  157. this._itemClickAction = this._createActionByOption("onItemClick")
  158. },
  159. _fireSelectionChangedAction: function(_ref) {
  160. var previousValue = _ref.previousValue,
  161. value = _ref.value;
  162. this._selectionChangedAction({
  163. item: value,
  164. previousItem: previousValue
  165. })
  166. },
  167. _fireItemClickAction: function(_ref2) {
  168. var event = _ref2.event,
  169. itemElement = _ref2.itemElement,
  170. itemData = _ref2.itemData;
  171. return this._itemClickAction({
  172. event: event,
  173. itemElement: itemElement,
  174. itemData: this._actionItem || itemData
  175. })
  176. },
  177. _actionButtonConfig: function() {
  178. return {
  179. text: this.option("text"),
  180. icon: this.option("icon"),
  181. elementAttr: {
  182. "class": DROP_DOWN_BUTTON_ACTION_CLASS
  183. }
  184. }
  185. },
  186. _getButtonGroupItems: function() {
  187. var items = [];
  188. items.push(this._actionButtonConfig());
  189. if (this.option("splitButton")) {
  190. items.push({
  191. icon: "spindown",
  192. width: 26,
  193. elementAttr: {
  194. "class": DROP_DOWN_BUTTON_TOGGLE_CLASS
  195. }
  196. })
  197. }
  198. return items
  199. },
  200. _buttonGroupItemClick: function(_ref3) {
  201. var event = _ref3.event,
  202. itemData = _ref3.itemData;
  203. var isActionButton = itemData.elementAttr.class === DROP_DOWN_BUTTON_ACTION_CLASS;
  204. var isToggleButton = itemData.elementAttr.class === DROP_DOWN_BUTTON_TOGGLE_CLASS;
  205. if (isToggleButton) {
  206. this.toggle()
  207. } else {
  208. if (isActionButton) {
  209. this._actionClickAction({
  210. event: event,
  211. selectedItem: this.option("selectedItem")
  212. });
  213. if (!this.option("splitButton")) {
  214. this.toggle()
  215. }
  216. }
  217. }
  218. },
  219. _buttonGroupOptions: function() {
  220. return (0, _extend.extend)({
  221. items: this._getButtonGroupItems(),
  222. focusStateEnabled: this.option("focusStateEnabled"),
  223. hoverStateEnabled: this.option("hoverStateEnabled"),
  224. onItemClick: this._buttonGroupItemClick.bind(this),
  225. width: "100%",
  226. height: "100%",
  227. stylingMode: this.option("stylingMode"),
  228. selectionMode: "none"
  229. }, this._getInnerOptionsCache("buttonGroupOptions"))
  230. },
  231. _renderPopupContent: function() {
  232. var $content = this._popup.$content();
  233. var template = this._getTemplateByOption("dropDownContentTemplate");
  234. $content.empty();
  235. this._popupContentId = "dx-" + new _guid2.default;
  236. this.setAria("id", this._popupContentId, $content);
  237. return template.render({
  238. container: _dom2.default.getPublicElement($content),
  239. model: this.option("items") || this._dataSource
  240. })
  241. },
  242. _popupOptions: function() {
  243. var _this2 = this;
  244. return (0, _extend.extend)({
  245. dragEnabled: false,
  246. focusStateEnabled: false,
  247. deferRendering: this.option("deferRendering"),
  248. minWidth: function() {
  249. return _this2.$element().outerWidth()
  250. },
  251. closeOnOutsideClick: function(e) {
  252. var $element = _this2.$element();
  253. var $buttonClicked = (0, _renderer2.default)(e.target).closest(".".concat(DROP_DOWN_BUTTON_CLASS));
  254. return !$buttonClicked.is($element)
  255. },
  256. showTitle: false,
  257. animation: {
  258. show: {
  259. type: "fade",
  260. duration: 0,
  261. from: 0,
  262. to: 1
  263. },
  264. hide: {
  265. type: "fade",
  266. duration: 400,
  267. from: 1,
  268. to: 0
  269. }
  270. },
  271. width: function() {
  272. return this.$element().outerWidth()
  273. }.bind(this),
  274. height: "auto",
  275. shading: false,
  276. visible: this.option("opened"),
  277. position: {
  278. of: this.$element(),
  279. collision: "flipfit",
  280. my: "top left",
  281. at: "bottom left",
  282. offset: {
  283. y: -1
  284. }
  285. }
  286. }, this._getInnerOptionsCache("dropDownOptions"))
  287. },
  288. _listOptions: function() {
  289. var _this3 = this;
  290. var selectedItemKey = this.option("selectedItemKey");
  291. var useSelectMode = this.option("useSelectMode");
  292. return {
  293. selectionMode: useSelectMode ? "single" : "none",
  294. focusStateEnabled: this.option("focusStateEnabled"),
  295. hoverStateEnabled: this.option("hoverStateEnabled"),
  296. selectedItemKeys: selectedItemKey && useSelectMode ? [selectedItemKey] : [],
  297. grouped: this.option("grouped"),
  298. keyExpr: this.option("keyExpr"),
  299. noDataText: this.option("noDataText"),
  300. displayExpr: this.option("displayExpr"),
  301. itemTemplate: this.option("itemTemplate"),
  302. items: this.option("items"),
  303. dataSource: this._dataSource,
  304. onItemClick: function(e) {
  305. if (!_this3.option("useSelectMode")) {
  306. _this3._lastSelectedItemData = e.itemData
  307. }
  308. _this3.option("selectedItemKey", _this3._keyGetter(e.itemData));
  309. var actionResult = _this3._fireItemClickAction(e);
  310. if (false !== actionResult) {
  311. _this3.toggle(false);
  312. _this3._buttonGroup.focus()
  313. }
  314. }
  315. }
  316. },
  317. _upDownKeyHandler: function() {
  318. if (this._popup && this._popup.option("visible") && this._list) {
  319. this._list.focus()
  320. } else {
  321. this.open()
  322. }
  323. },
  324. _escHandler: function() {
  325. this.close();
  326. this._buttonGroup.focus()
  327. },
  328. _renderPopup: function() {
  329. var $popup = (0, _renderer2.default)("<div>");
  330. this.$element().append($popup);
  331. this._popup = this._createComponent($popup, _popup2.default, this._popupOptions());
  332. this._popup.$content().addClass(DROP_DOWN_BUTTON_CONTENT);
  333. this._popup._wrapper().addClass(DROP_DOWN_BUTTON_POPUP_WRAPPER_CLASS);
  334. this._popup.on("hiding", this._popupHidingHandler.bind(this));
  335. this._popup.on("showing", this._popupShowingHandler.bind(this));
  336. this._renderPopupContent();
  337. this._bindInnerWidgetOptions(this._popup, "dropDownOptions")
  338. },
  339. _popupHidingHandler: function() {
  340. this.option("opened", false);
  341. this.setAria({
  342. expanded: false,
  343. owns: void 0
  344. })
  345. },
  346. _popupShowingHandler: function() {
  347. this.option("opened", true);
  348. this.setAria({
  349. expanded: true,
  350. owns: this._popupContentId
  351. })
  352. },
  353. _renderAdditionalIcon: function() {
  354. if (this.option("splitButton") || !this.option("showArrowIcon")) {
  355. return
  356. }
  357. var $firstButtonContent = this._buttonGroup.$element().find(".".concat(DX_BUTTON_CONTENT_CLASS)).eq(0);
  358. var $iconElement = (0, _icon.getImageContainer)("spindown");
  359. $iconElement.addClass(DX_ICON_RIGHT_CLASS).appendTo($firstButtonContent)
  360. },
  361. _renderButtonGroup: function() {
  362. var $buttonGroup = this._buttonGroup && this._buttonGroup.$element() || (0, _renderer2.default)("<div>");
  363. if (!this._buttonGroup) {
  364. this.$element().append($buttonGroup)
  365. }
  366. this._buttonGroup = this._createComponent($buttonGroup, _button_group2.default, this._buttonGroupOptions());
  367. this._buttonGroup.registerKeyHandler("downArrow", this._upDownKeyHandler.bind(this));
  368. this._buttonGroup.registerKeyHandler("tab", this.close.bind(this));
  369. this._buttonGroup.registerKeyHandler("upArrow", this._upDownKeyHandler.bind(this));
  370. this._buttonGroup.registerKeyHandler("escape", this._escHandler.bind(this));
  371. this._renderAdditionalIcon();
  372. this._bindInnerWidgetOptions(this._buttonGroup, "buttonGroupOptions")
  373. },
  374. toggle: function(visible) {
  375. this._popup || this._renderPopup();
  376. return this._popup.toggle(visible)
  377. },
  378. open: function() {
  379. return this.toggle(true)
  380. },
  381. close: function() {
  382. return this.toggle(false)
  383. },
  384. _setListOption: function(name, value) {
  385. this._list && this._list.option(name, value)
  386. },
  387. _getDisplayValue: function(item) {
  388. var isPrimitiveItem = !(0, _type.isPlainObject)(item);
  389. var displayValue = isPrimitiveItem ? item : this._displayGetter(item);
  390. return !(0, _type.isPlainObject)(displayValue) ? String((0, _common.ensureDefined)(displayValue, "")) : ""
  391. },
  392. _updateActionButton: function(selectedItem) {
  393. if (this.option("useSelectMode")) {
  394. this.option({
  395. text: this._getDisplayValue(selectedItem),
  396. icon: (0, _type.isPlainObject)(selectedItem) ? selectedItem.icon : void 0
  397. })
  398. }
  399. this._setOptionSilent("selectedItem", selectedItem)
  400. },
  401. _clean: function() {
  402. this._list && this._list.$element().remove();
  403. this._popup && this._popup.$element().remove()
  404. },
  405. _selectedItemKeyChanged: function(value) {
  406. var _this4 = this;
  407. this._setListOption("selectedItemKeys", this.option("useSelectMode") && (0, _type.isDefined)(value) ? [value] : []);
  408. var previousItem = this.option("selectedItem");
  409. this._loadSelectedItem().done(function(selectedItem) {
  410. _this4._updateActionButton(selectedItem);
  411. if (_this4._displayGetter(previousItem) !== _this4._displayGetter(selectedItem)) {
  412. _this4._fireSelectionChangedAction({
  413. previousValue: previousItem,
  414. value: selectedItem
  415. })
  416. }
  417. })
  418. },
  419. _selectModeChanged: function(value) {
  420. if (value) {
  421. this._setListOption("selectionMode", "single");
  422. var selectedItemKey = this.option("selectedItemKey");
  423. this._setListOption("selectedItemKeys", selectedItemKey ? [selectedItemKey] : [])
  424. } else {
  425. this._setListOption("selectionMode", "none");
  426. this.option({
  427. selectedItemKey: void 0,
  428. selectedItem: void 0
  429. })
  430. }
  431. },
  432. _updateItemCollection: function(optionName) {
  433. this._setWidgetOption("_list", [optionName]);
  434. this._setListOption("selectedItemKeys", []);
  435. this._loadSelectedItem().done(this._updateActionButton.bind(this))
  436. },
  437. _optionChanged: function(args) {
  438. var name = args.name,
  439. value = args.value;
  440. switch (args.name) {
  441. case "useSelectMode":
  442. this._selectModeChanged(args.value);
  443. break;
  444. case "splitButton":
  445. this._renderButtonGroup();
  446. break;
  447. case "displayExpr":
  448. this._compileDisplayGetter();
  449. break;
  450. case "keyExpr":
  451. this._compileKeyGetter();
  452. break;
  453. case "buttonGroupOptions":
  454. this._innerOptionChanged(this._buttonGroup, args);
  455. break;
  456. case "dropDownOptions":
  457. this._innerOptionChanged(this._popup, args);
  458. break;
  459. case "opened":
  460. this.toggle(value);
  461. break;
  462. case "focusStateEnabled":
  463. case "hoverStateEnabled":
  464. this._setListOption(name, value);
  465. this._buttonGroup.option(name, value);
  466. break;
  467. case "items":
  468. this._dataSource = null;
  469. this._itemsToDataSource();
  470. this._updateItemCollection(name);
  471. break;
  472. case "dataSource":
  473. this._initDataSource();
  474. this._updateItemCollection(name);
  475. break;
  476. case "icon":
  477. this._buttonGroup.option("items[0]", (0, _extend.extend)({}, this._actionButtonConfig(), {
  478. icon: value
  479. }));
  480. this._renderAdditionalIcon();
  481. break;
  482. case "text":
  483. this._buttonGroup.option("items[0]", (0, _extend.extend)({}, this._actionButtonConfig(), {
  484. text: value
  485. }));
  486. this._renderAdditionalIcon();
  487. break;
  488. case "showArrowIcon":
  489. if (!value) {
  490. this._buttonGroup.$element().find(".".concat(DX_ICON_RIGHT_CLASS)).remove()
  491. }
  492. this._renderAdditionalIcon();
  493. break;
  494. case "width":
  495. case "height":
  496. this.callBase(args);
  497. this._popup && this._popup.repaint();
  498. break;
  499. case "stylingMode":
  500. this._buttonGroup.option(name, value);
  501. break;
  502. case "itemTemplate":
  503. case "grouped":
  504. case "noDataText":
  505. case "groupTemplate":
  506. this._setListOption(name, value);
  507. break;
  508. case "dropDownContentTemplate":
  509. this._popup && this._renderPopupContent();
  510. break;
  511. case "selectedItemKey":
  512. this._selectedItemKeyChanged(value);
  513. break;
  514. case "selectedItem":
  515. break;
  516. case "onItemClick":
  517. this._createItemClickAction();
  518. break;
  519. case "onButtonClick":
  520. this._createActionClickAction();
  521. break;
  522. case "onSelectionChanged":
  523. this._createSelectionChangedAction();
  524. break;
  525. case "deferRendering":
  526. if (!value && !this._popup) {
  527. this._renderPopup()
  528. }
  529. break;
  530. default:
  531. this.callBase(args)
  532. }
  533. }
  534. }).include(_data_helper2.default);
  535. (0, _component_registrator2.default)("dxDropDownButton", DropDownButton);
  536. module.exports = DropDownButton;
  537. module.exports.default = module.exports;