ui.toolbar.base.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /**
  2. * DevExtreme (ui/toolbar/ui.toolbar.base.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 _themes = require("../themes");
  13. var _themes2 = _interopRequireDefault(_themes);
  14. var _common = require("../../core/utils/common");
  15. var _common2 = _interopRequireDefault(_common);
  16. var _type = require("../../core/utils/type");
  17. var _component_registrator = require("../../core/component_registrator");
  18. var _component_registrator2 = _interopRequireDefault(_component_registrator);
  19. var _array = require("../../core/utils/array");
  20. var _extend = require("../../core/utils/extend");
  21. var _iterator = require("../../core/utils/iterator");
  22. var _uiCollection_widget = require("../collection/ui.collection_widget.async");
  23. var _uiCollection_widget2 = _interopRequireDefault(_uiCollection_widget);
  24. var _promise = require("../../core/polyfills/promise");
  25. var _promise2 = _interopRequireDefault(_promise);
  26. var _bindable_template = require("../widget/bindable_template");
  27. var _bindable_template2 = _interopRequireDefault(_bindable_template);
  28. var _fx = require("../../animation/fx");
  29. var _fx2 = _interopRequireDefault(_fx);
  30. function _interopRequireDefault(obj) {
  31. return obj && obj.__esModule ? obj : {
  32. "default": obj
  33. }
  34. }
  35. var TOOLBAR_CLASS = "dx-toolbar";
  36. var TOOLBAR_BEFORE_CLASS = "dx-toolbar-before";
  37. var TOOLBAR_CENTER_CLASS = "dx-toolbar-center";
  38. var TOOLBAR_AFTER_CLASS = "dx-toolbar-after";
  39. var TOOLBAR_BOTTOM_CLASS = "dx-toolbar-bottom";
  40. var TOOLBAR_MINI_CLASS = "dx-toolbar-mini";
  41. var TOOLBAR_ITEM_CLASS = "dx-toolbar-item";
  42. var TOOLBAR_LABEL_CLASS = "dx-toolbar-label";
  43. var TOOLBAR_BUTTON_CLASS = "dx-toolbar-button";
  44. var TOOLBAR_ITEMS_CONTAINER_CLASS = "dx-toolbar-items-container";
  45. var TOOLBAR_GROUP_CLASS = "dx-toolbar-group";
  46. var TOOLBAR_COMPACT_CLASS = "dx-toolbar-compact";
  47. var TOOLBAR_LABEL_SELECTOR = "." + TOOLBAR_LABEL_CLASS;
  48. var TEXT_BUTTON_MODE = "text";
  49. var DEFAULT_BUTTON_TYPE = "default";
  50. var TOOLBAR_ITEM_DATA_KEY = "dxToolbarItemDataKey";
  51. var ToolbarBase = _uiCollection_widget2.default.inherit({
  52. compactMode: false,
  53. ctor: function(element, options) {
  54. this._userOptions = options || {};
  55. this.callBase(element, options)
  56. },
  57. _getSynchronizableOptionsForCreateComponent: function() {
  58. return this.callBase().filter(function(item) {
  59. return "disabled" !== item
  60. })
  61. },
  62. _initTemplates: function() {
  63. this.callBase();
  64. var template = new _bindable_template2.default(function($container, data, rawModel) {
  65. if ((0, _type.isPlainObject)(data)) {
  66. if (data.text) {
  67. $container.text(data.text).wrapInner("<div>")
  68. }
  69. if (data.html) {
  70. $container.html(data.html)
  71. }
  72. if ("dxButton" === data.widget) {
  73. if (this.option("useFlatButtons")) {
  74. data.options = data.options || {};
  75. data.options.stylingMode = data.options.stylingMode || TEXT_BUTTON_MODE
  76. }
  77. if (this.option("useDefaultButtons")) {
  78. data.options = data.options || {};
  79. data.options.type = data.options.type || DEFAULT_BUTTON_TYPE
  80. }
  81. }
  82. } else {
  83. $container.text(String(data))
  84. }
  85. this._getTemplate("dx-polymorph-widget").render({
  86. container: $container,
  87. model: rawModel,
  88. parent: this
  89. })
  90. }.bind(this), ["text", "html", "widget", "options"], this.option("integrationOptions.watchMethod"));
  91. this._defaultTemplates.item = template;
  92. this._defaultTemplates.menuItem = template
  93. },
  94. _getDefaultOptions: function() {
  95. return (0, _extend.extend)(this.callBase(), {
  96. renderAs: "topToolbar",
  97. grouped: false,
  98. useFlatButtons: false,
  99. useDefaultButtons: false
  100. })
  101. },
  102. _defaultOptionsRules: function() {
  103. return this.callBase().concat([{
  104. device: function() {
  105. return _themes2.default.isMaterial()
  106. },
  107. options: {
  108. useFlatButtons: true
  109. }
  110. }])
  111. },
  112. _itemContainer: function() {
  113. return this._$toolbarItemsContainer.find(["." + TOOLBAR_BEFORE_CLASS, "." + TOOLBAR_CENTER_CLASS, "." + TOOLBAR_AFTER_CLASS].join(","))
  114. },
  115. _itemClass: function() {
  116. return TOOLBAR_ITEM_CLASS
  117. },
  118. _itemDataKey: function() {
  119. return TOOLBAR_ITEM_DATA_KEY
  120. },
  121. _buttonClass: function() {
  122. return TOOLBAR_BUTTON_CLASS
  123. },
  124. _dimensionChanged: function() {
  125. this._arrangeItems();
  126. this._applyCompactMode()
  127. },
  128. _initMarkup: function() {
  129. this._renderToolbar();
  130. this._renderSections();
  131. this.callBase();
  132. this.setAria("role", "toolbar")
  133. },
  134. _waitParentAnimationFinished: function() {
  135. var $element = this.$element();
  136. var timeout = 15;
  137. return new _promise2.default(function(resolve) {
  138. var check = function() {
  139. var readyToResolve = true;
  140. $element.parents().each(function(_, parent) {
  141. if (_fx2.default.isAnimating((0, _renderer2.default)(parent))) {
  142. readyToResolve = false;
  143. return false
  144. }
  145. });
  146. if (readyToResolve) {
  147. resolve()
  148. }
  149. return readyToResolve
  150. };
  151. var runCheck = function runCheck() {
  152. setTimeout(function() {
  153. return check() || runCheck()
  154. }, timeout)
  155. };
  156. $element.width() > 0 && check() || runCheck()
  157. })
  158. },
  159. _render: function() {
  160. this.callBase();
  161. this._renderItemsAsync();
  162. if (_themes2.default.isMaterial()) {
  163. _promise2.default.all([this._waitParentAnimationFinished(), this._checkWebFontForLabelsLoaded()]).then(this._dimensionChanged.bind(this))
  164. }
  165. },
  166. _postProcessRenderItems: function() {
  167. this._arrangeItems()
  168. },
  169. _renderToolbar: function() {
  170. this.$element().addClass(TOOLBAR_CLASS).toggleClass(TOOLBAR_BOTTOM_CLASS, "bottomToolbar" === this.option("renderAs"));
  171. this._$toolbarItemsContainer = (0, _renderer2.default)("<div>").addClass(TOOLBAR_ITEMS_CONTAINER_CLASS).appendTo(this.$element())
  172. },
  173. _renderSections: function() {
  174. var $container = this._$toolbarItemsContainer;
  175. var that = this;
  176. (0, _iterator.each)(["before", "center", "after"], function() {
  177. var sectionClass = "dx-toolbar-" + this;
  178. var $section = $container.find("." + sectionClass);
  179. if (!$section.length) {
  180. that["_$" + this + "Section"] = $section = (0, _renderer2.default)("<div>").addClass(sectionClass).appendTo($container)
  181. }
  182. })
  183. },
  184. _checkWebFontForLabelsLoaded: function() {
  185. var $labels = this.$element().find(TOOLBAR_LABEL_SELECTOR);
  186. var promises = [];
  187. $labels.each(function(_, label) {
  188. var text = (0, _renderer2.default)(label).text();
  189. var fontWeight = (0, _renderer2.default)(label).css("fontWeight");
  190. promises.push(_themes2.default.waitWebFont(text, fontWeight))
  191. });
  192. return _promise2.default.all(promises)
  193. },
  194. _arrangeItems: function(elementWidth) {
  195. elementWidth = elementWidth || this.$element().width();
  196. this._$centerSection.css({
  197. margin: "0 auto",
  198. "float": "none"
  199. });
  200. var beforeRect = this._$beforeSection.get(0).getBoundingClientRect();
  201. var afterRect = this._$afterSection.get(0).getBoundingClientRect();
  202. this._alignCenterSection(beforeRect, afterRect, elementWidth);
  203. var $label = this._$toolbarItemsContainer.find(TOOLBAR_LABEL_SELECTOR).eq(0);
  204. var $section = $label.parent();
  205. if (!$label.length) {
  206. return
  207. }
  208. var labelOffset = beforeRect.width ? beforeRect.width : $label.position().left;
  209. var widthBeforeSection = $section.hasClass(TOOLBAR_BEFORE_CLASS) ? 0 : labelOffset;
  210. var widthAfterSection = $section.hasClass(TOOLBAR_AFTER_CLASS) ? 0 : afterRect.width;
  211. var elemsAtSectionWidth = 0;
  212. $section.children().not(TOOLBAR_LABEL_SELECTOR).each(function() {
  213. elemsAtSectionWidth += (0, _renderer2.default)(this).outerWidth()
  214. });
  215. var freeSpace = elementWidth - elemsAtSectionWidth;
  216. var sectionMaxWidth = Math.max(freeSpace - widthBeforeSection - widthAfterSection, 0);
  217. if ($section.hasClass(TOOLBAR_BEFORE_CLASS)) {
  218. this._alignSection(this._$beforeSection, sectionMaxWidth)
  219. } else {
  220. var labelPaddings = $label.outerWidth() - $label.width();
  221. $label.css("maxWidth", sectionMaxWidth - labelPaddings)
  222. }
  223. },
  224. _alignCenterSection: function(beforeRect, afterRect, elementWidth) {
  225. this._alignSection(this._$centerSection, elementWidth - beforeRect.width - afterRect.width);
  226. var isRTL = this.option("rtlEnabled");
  227. var leftRect = isRTL ? afterRect : beforeRect;
  228. var rightRect = isRTL ? beforeRect : afterRect;
  229. var centerRect = this._$centerSection.get(0).getBoundingClientRect();
  230. if (leftRect.right > centerRect.left || centerRect.right > rightRect.left) {
  231. this._$centerSection.css({
  232. marginLeft: leftRect.width,
  233. marginRight: rightRect.width,
  234. "float": leftRect.width > rightRect.width ? "none" : "right"
  235. })
  236. }
  237. },
  238. _alignSection: function($section, maxWidth) {
  239. var $labels = $section.find(TOOLBAR_LABEL_SELECTOR);
  240. var labels = $labels.toArray();
  241. maxWidth -= this._getCurrentLabelsPaddings(labels);
  242. var currentWidth = this._getCurrentLabelsWidth(labels);
  243. var difference = Math.abs(currentWidth - maxWidth);
  244. if (maxWidth < currentWidth) {
  245. labels = labels.reverse();
  246. this._alignSectionLabels(labels, difference, false)
  247. } else {
  248. this._alignSectionLabels(labels, difference, true)
  249. }
  250. },
  251. _alignSectionLabels: function(labels, difference, expanding) {
  252. var getRealLabelWidth = function(label) {
  253. return label.getBoundingClientRect().width
  254. };
  255. for (var i = 0; i < labels.length; i++) {
  256. var $label = (0, _renderer2.default)(labels[i]);
  257. var currentLabelWidth = Math.ceil(getRealLabelWidth(labels[i]));
  258. var labelMaxWidth;
  259. if (expanding) {
  260. $label.css("maxWidth", "inherit")
  261. }
  262. var possibleLabelWidth = Math.ceil(expanding ? getRealLabelWidth(labels[i]) : currentLabelWidth);
  263. if (possibleLabelWidth < difference) {
  264. labelMaxWidth = expanding ? possibleLabelWidth : 0;
  265. difference -= possibleLabelWidth
  266. } else {
  267. labelMaxWidth = expanding ? currentLabelWidth + difference : currentLabelWidth - difference;
  268. $label.css("maxWidth", labelMaxWidth);
  269. break
  270. }
  271. $label.css("maxWidth", labelMaxWidth)
  272. }
  273. },
  274. _applyCompactMode: function() {
  275. var $element = this.$element();
  276. $element.removeClass(TOOLBAR_COMPACT_CLASS);
  277. if (this.option("compactMode") && this._getSummaryItemsWidth(this.itemElements(), true) > $element.width()) {
  278. $element.addClass(TOOLBAR_COMPACT_CLASS)
  279. }
  280. },
  281. _getCurrentLabelsWidth: function(labels) {
  282. var width = 0;
  283. labels.forEach(function(label, index) {
  284. width += (0, _renderer2.default)(label).outerWidth()
  285. });
  286. return width
  287. },
  288. _getCurrentLabelsPaddings: function(labels) {
  289. var padding = 0;
  290. labels.forEach(function(label, index) {
  291. padding += (0, _renderer2.default)(label).outerWidth() - (0, _renderer2.default)(label).width()
  292. });
  293. return padding
  294. },
  295. _renderItem: function(index, item, itemContainer, $after) {
  296. var location = item.location || "center";
  297. var container = itemContainer || this["_$" + location + "Section"];
  298. var itemHasText = !!(item.text || item.html);
  299. var itemElement = this.callBase(index, item, container, $after);
  300. itemElement.toggleClass(this._buttonClass(), !itemHasText).toggleClass(TOOLBAR_LABEL_CLASS, itemHasText).addClass(item.cssClass);
  301. return itemElement
  302. },
  303. _renderGroupedItems: function() {
  304. var that = this;
  305. (0, _iterator.each)(this.option("items"), function(groupIndex, group) {
  306. var groupItems = group.items;
  307. var $container = (0, _renderer2.default)("<div>").addClass(TOOLBAR_GROUP_CLASS);
  308. var location = group.location || "center";
  309. if (!groupItems || !groupItems.length) {
  310. return
  311. }(0, _iterator.each)(groupItems, function(itemIndex, item) {
  312. that._renderItem(itemIndex, item, $container, null)
  313. });
  314. that._$toolbarItemsContainer.find(".dx-toolbar-" + location).append($container)
  315. })
  316. },
  317. _renderItems: function(items) {
  318. var grouped = this.option("grouped") && items.length && items[0].items;
  319. grouped ? this._renderGroupedItems() : this.callBase(items)
  320. },
  321. _getToolbarItems: function() {
  322. return this.option("items") || []
  323. },
  324. _renderContentImpl: function() {
  325. var items = this._getToolbarItems();
  326. this.$element().toggleClass(TOOLBAR_MINI_CLASS, 0 === items.length);
  327. if (this._renderedItemsCount) {
  328. this._renderItems(items.slice(this._renderedItemsCount))
  329. } else {
  330. this._renderItems(items)
  331. }
  332. this._applyCompactMode()
  333. },
  334. _renderEmptyMessage: _common2.default.noop,
  335. _clean: function() {
  336. this._$toolbarItemsContainer.children().empty();
  337. this.$element().empty()
  338. },
  339. _visibilityChanged: function(visible) {
  340. if (visible) {
  341. this._arrangeItems()
  342. }
  343. },
  344. _isVisible: function() {
  345. return this.$element().width() > 0 && this.$element().height() > 0
  346. },
  347. _getIndexByItem: function(item) {
  348. return (0, _array.inArray)(item, this._getToolbarItems())
  349. },
  350. _itemOptionChanged: function(item, property, value) {
  351. this.callBase.apply(this, [item, property, value]);
  352. this._arrangeItems()
  353. },
  354. _optionChanged: function(args) {
  355. var name = args.name;
  356. switch (name) {
  357. case "width":
  358. this.callBase.apply(this, arguments);
  359. this._dimensionChanged();
  360. break;
  361. case "renderAs":
  362. case "useFlatButtons":
  363. case "useDefaultButtons":
  364. this._invalidate();
  365. break;
  366. case "compactMode":
  367. this._applyCompactMode();
  368. break;
  369. case "grouped":
  370. break;
  371. default:
  372. this.callBase.apply(this, arguments)
  373. }
  374. }
  375. });
  376. (0, _component_registrator2.default)("dxToolbarBase", ToolbarBase);
  377. module.exports = ToolbarBase;