ui.drawer.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /**
  2. * DevExtreme (ui/drawer/ui.drawer.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 _events_engine = require("../../events/core/events_engine");
  13. var _events_engine2 = _interopRequireDefault(_events_engine);
  14. var _type = require("../../core/utils/type");
  15. var _type2 = _interopRequireDefault(_type);
  16. var _dom = require("../../core/utils/dom");
  17. var _component_registrator = require("../../core/component_registrator");
  18. var _component_registrator2 = _interopRequireDefault(_component_registrator);
  19. var _extend = require("../../core/utils/extend");
  20. var _ui = require("../widget/ui.widget");
  21. var _ui2 = _interopRequireDefault(_ui);
  22. var _empty_template = require("../widget/empty_template");
  23. var _empty_template2 = _interopRequireDefault(_empty_template);
  24. var _window = require("../../core/utils/window");
  25. var _uiDrawerRenderingStrategy = require("./ui.drawer.rendering.strategy.push");
  26. var _uiDrawerRenderingStrategy2 = _interopRequireDefault(_uiDrawerRenderingStrategy);
  27. var _uiDrawerRenderingStrategy3 = require("./ui.drawer.rendering.strategy.shrink");
  28. var _uiDrawerRenderingStrategy4 = _interopRequireDefault(_uiDrawerRenderingStrategy3);
  29. var _uiDrawerRenderingStrategy5 = require("./ui.drawer.rendering.strategy.overlap");
  30. var _uiDrawerRenderingStrategy6 = _interopRequireDefault(_uiDrawerRenderingStrategy5);
  31. var _uiDrawerRendering = require("./ui.drawer.rendering.strategy");
  32. var _click = require("../../events/click");
  33. var _click2 = _interopRequireDefault(_click);
  34. var _fx = require("../../animation/fx");
  35. var _fx2 = _interopRequireDefault(_fx);
  36. var _deferred = require("../../core/utils/deferred");
  37. function _interopRequireDefault(obj) {
  38. return obj && obj.__esModule ? obj : {
  39. "default": obj
  40. }
  41. }
  42. var DRAWER_CLASS = "dx-drawer";
  43. var DRAWER_WRAPPER_CLASS = "dx-drawer-wrapper";
  44. var DRAWER_PANEL_CONTENT_CLASS = "dx-drawer-panel-content";
  45. var DRAWER_CONTENT_CLASS = "dx-drawer-content";
  46. var DRAWER_SHADER_CLASS = "dx-drawer-shader";
  47. var INVISIBLE_STATE_CLASS = "dx-state-invisible";
  48. var OPENED_STATE_CLASS = "dx-drawer-opened";
  49. var ANONYMOUS_TEMPLATE_NAME = "content";
  50. var Drawer = _ui2.default.inherit({
  51. _getDefaultOptions: function() {
  52. return (0, _extend.extend)(this.callBase(), {
  53. position: "left",
  54. opened: false,
  55. minSize: null,
  56. maxSize: null,
  57. shading: false,
  58. template: "panel",
  59. openedStateMode: "shrink",
  60. revealMode: "slide",
  61. animationEnabled: true,
  62. animationDuration: 400,
  63. closeOnOutsideClick: false,
  64. contentTemplate: "content",
  65. target: void 0
  66. })
  67. },
  68. _getAnonymousTemplateName: function() {
  69. return ANONYMOUS_TEMPLATE_NAME
  70. },
  71. _init: function() {
  72. this.callBase();
  73. this._initStrategy();
  74. this.$element().addClass(DRAWER_CLASS);
  75. this._animations = [];
  76. this._animationPromise = void 0;
  77. this._whenPanelRendered = void 0;
  78. this._whenPanelRefreshed = void 0;
  79. this._initHideTopOverlayHandler();
  80. this._initContentMarkup()
  81. },
  82. _initStrategy: function() {
  83. var mode = this.option("openedStateMode");
  84. var Strategy = this._getDefaultStrategy();
  85. if ("push" === mode) {
  86. Strategy = _uiDrawerRenderingStrategy2.default
  87. }
  88. if ("shrink" === mode) {
  89. Strategy = _uiDrawerRenderingStrategy4.default
  90. }
  91. if ("overlap" === mode) {
  92. Strategy = _uiDrawerRenderingStrategy6.default
  93. }
  94. this._strategy = new Strategy(this)
  95. },
  96. _initContentMarkup: function() {
  97. this._$wrapper = (0, _renderer2.default)("<div>").addClass(DRAWER_WRAPPER_CLASS);
  98. this._$contentWrapper = (0, _renderer2.default)("<div>").addClass(DRAWER_CONTENT_CLASS);
  99. this._$wrapper.append(this._$contentWrapper);
  100. this.$element().append(this._$wrapper)
  101. },
  102. _getDefaultStrategy: function() {
  103. return _uiDrawerRenderingStrategy2.default
  104. },
  105. _initHideTopOverlayHandler: function() {
  106. this._hideMenuHandler = this.hide.bind(this)
  107. },
  108. _initTemplates: function() {
  109. this.callBase();
  110. this._defaultTemplates.panel = new _empty_template2.default(this);
  111. this._defaultTemplates.content = new _empty_template2.default(this)
  112. },
  113. _initCloseOnOutsideClickHandler: function() {
  114. _events_engine2.default.off(this._$contentWrapper, _click2.default.name);
  115. _events_engine2.default.on(this._$contentWrapper, _click2.default.name, this._outsideClickHandler.bind(this))
  116. },
  117. _outsideClickHandler: function(e) {
  118. var closeOnOutsideClick = this.option("closeOnOutsideClick");
  119. if (_type2.default.isFunction(closeOnOutsideClick)) {
  120. closeOnOutsideClick = closeOnOutsideClick(e)
  121. }
  122. if (closeOnOutsideClick && this.option("opened")) {
  123. this.stopAnimations();
  124. if (this.option("shading")) {
  125. e.preventDefault()
  126. }
  127. this.hide();
  128. this._toggleShaderVisibility(false)
  129. }
  130. },
  131. _initMarkup: function() {
  132. this.callBase();
  133. this._toggleVisibleClass(this.option("opened"));
  134. this._renderPanelElement();
  135. this._refreshModeClass();
  136. this._refreshRevealModeClass();
  137. this._renderShader();
  138. this._whenPanelRendered = new _deferred.Deferred;
  139. this._strategy.renderPanel(this._getTemplate(this.option("template")), this._whenPanelRendered);
  140. var contentTemplateOption = this.option("contentTemplate");
  141. var contentTemplate = this._getTemplate(contentTemplateOption);
  142. var transclude = this._getAnonymousTemplateName() === contentTemplateOption;
  143. contentTemplate && contentTemplate.render({
  144. container: this.viewContent(),
  145. noModel: true,
  146. transclude: transclude
  147. });
  148. this._initCloseOnOutsideClickHandler();
  149. this._refreshPositionClass()
  150. },
  151. _render: function() {
  152. var _this = this;
  153. this._initSize();
  154. this.callBase();
  155. this._whenPanelRendered.always(function() {
  156. _this._initSize();
  157. _this._strategy.setPanelSize("slide" === _this.option("revealMode") || !_this.isHorizontalDirection());
  158. _this._renderPosition(_this.option("opened"), false)
  159. })
  160. },
  161. _renderPanelElement: function() {
  162. this._$panel = (0, _renderer2.default)("<div>").addClass(DRAWER_PANEL_CONTENT_CLASS);
  163. this._$wrapper.append(this._$panel)
  164. },
  165. _refreshModeClass: function(prevClass) {
  166. prevClass && this.$element().removeClass(DRAWER_CLASS + "-" + prevClass);
  167. this.$element().addClass(DRAWER_CLASS + "-" + this.option("openedStateMode"))
  168. },
  169. _refreshPositionClass: function(prevClass) {
  170. prevClass && this.$element().removeClass(DRAWER_CLASS + "-" + prevClass);
  171. var position = this.getDrawerPosition();
  172. this.$element().addClass(DRAWER_CLASS + "-" + position);
  173. this._orderContent(position)
  174. },
  175. _orderContent: function(position) {
  176. if (this._strategy.needOrderContent(position, this.option("rtlEnabled"))) {
  177. this._$wrapper.prepend(this._$contentWrapper)
  178. } else {
  179. this._$wrapper.prepend(this._$panel)
  180. }
  181. },
  182. _refreshRevealModeClass: function(prevClass) {
  183. prevClass && this.$element().removeClass(DRAWER_CLASS + "-" + prevClass);
  184. this.$element().addClass(DRAWER_CLASS + "-" + this.option("revealMode"))
  185. },
  186. _renderShader: function() {
  187. this._$shader = this._$shader || (0, _renderer2.default)("<div>").addClass(DRAWER_SHADER_CLASS);
  188. this._$shader.appendTo(this.viewContent());
  189. this._toggleShaderVisibility(this.option("opened"))
  190. },
  191. _initSize: function() {
  192. var realPanelSize = this.isHorizontalDirection() ? this.getRealPanelWidth() : this.getRealPanelHeight();
  193. this._maxSize = this.option("maxSize") || realPanelSize;
  194. this._minSize = this.option("minSize") || 0
  195. },
  196. getDrawerPosition: function() {
  197. var position = this.option("position");
  198. var rtl = this.option("rtlEnabled");
  199. if ("before" === position) {
  200. return rtl ? "right" : "left"
  201. }
  202. if ("after" === position) {
  203. return rtl ? "left" : "right"
  204. }
  205. return position
  206. },
  207. getOverlayTarget: function() {
  208. return this.option("target") || this._$wrapper
  209. },
  210. getOverlay: function() {
  211. return this._overlay
  212. },
  213. getMaxSize: function() {
  214. return this._maxSize
  215. },
  216. getMinSize: function() {
  217. return this._minSize
  218. },
  219. getRealPanelWidth: function() {
  220. if ((0, _window.hasWindow)()) {
  221. if (_type2.default.isDefined(this.option("templateSize"))) {
  222. return this.option("templateSize")
  223. } else {
  224. return this.getElementWidth(this._strategy.getPanelContent())
  225. }
  226. } else {
  227. return 0
  228. }
  229. },
  230. getElementWidth: function($element) {
  231. var $children = $element.children();
  232. return $children.length ? $children.eq(0).get(0).getBoundingClientRect().width : $element.get(0).getBoundingClientRect().width
  233. },
  234. getRealPanelHeight: function() {
  235. if ((0, _window.hasWindow)()) {
  236. if (_type2.default.isDefined(this.option("templateSize"))) {
  237. return this.option("templateSize")
  238. } else {
  239. return this.getElementHeight(this._strategy.getPanelContent())
  240. }
  241. } else {
  242. return 0
  243. }
  244. },
  245. getElementHeight: function($element) {
  246. var $children = $element.children();
  247. return $children.length ? $children.eq(0).get(0).getBoundingClientRect().height : $element.get(0).getBoundingClientRect().height
  248. },
  249. isHorizontalDirection: function() {
  250. var position = this.getDrawerPosition();
  251. return "left" === position || "right" === position
  252. },
  253. stopAnimations: function(jumpToEnd) {
  254. _fx2.default.stop(this._$shader, jumpToEnd);
  255. _fx2.default.stop((0, _renderer2.default)(this.content()), jumpToEnd);
  256. _fx2.default.stop((0, _renderer2.default)(this.viewContent()), jumpToEnd);
  257. var overlay = this.getOverlay();
  258. overlay && _fx2.default.stop((0, _renderer2.default)(overlay.$content()), jumpToEnd)
  259. },
  260. setZIndex: function(zIndex) {
  261. this._$shader.css("zIndex", zIndex - 1);
  262. this._$panel.css("zIndex", zIndex)
  263. },
  264. resizeContent: function() {
  265. (0, _dom.triggerResizeEvent)(this.viewContent())
  266. },
  267. _isInvertedPosition: function() {
  268. var position = this.getDrawerPosition();
  269. return "right" === position || "bottom" === position
  270. },
  271. _renderPosition: function(offset, animate, jumpToEnd) {
  272. this.stopAnimations(jumpToEnd);
  273. this._animations = [];
  274. animate = _type2.default.isDefined(animate) ? animate && this.option("animationEnabled") : this.option("animationEnabled");
  275. if (!(0, _window.hasWindow)()) {
  276. return
  277. }
  278. var duration = this.option("animationDuration");
  279. offset && this._toggleShaderVisibility(offset);
  280. this._strategy.renderPosition(offset, animate);
  281. this._strategy.renderShaderVisibility(offset, animate, duration)
  282. },
  283. _animationCompleteHandler: function() {
  284. this.resizeContent();
  285. if (this._animationPromise) {
  286. this._animationPromise.resolve();
  287. this._animations = []
  288. }
  289. },
  290. _getPositionCorrection: function() {
  291. return this._isInvertedPosition() ? -1 : 1
  292. },
  293. _dispose: function() {
  294. _uiDrawerRendering.animation.complete((0, _renderer2.default)(this.viewContent()));
  295. this.callBase()
  296. },
  297. _visibilityChanged: function(visible) {
  298. if (visible) {
  299. this._dimensionChanged()
  300. }
  301. },
  302. _dimensionChanged: function() {
  303. this._initSize();
  304. this._strategy.setPanelSize("slide" === this.option("revealMode"))
  305. },
  306. _toggleShaderVisibility: function(visible) {
  307. if (this.option("shading")) {
  308. this._$shader.toggleClass(INVISIBLE_STATE_CLASS, !visible);
  309. this._$shader.css("visibility", visible ? "visible" : "hidden")
  310. } else {
  311. this._$shader.toggleClass(INVISIBLE_STATE_CLASS, true)
  312. }
  313. },
  314. _toggleVisibleClass: function(opened) {
  315. this.$element().toggleClass(OPENED_STATE_CLASS, opened)
  316. },
  317. _refreshPanel: function() {
  318. var _this2 = this;
  319. this._setInitialViewContentPosition();
  320. this._cleanPanel();
  321. this._renderPanelElement();
  322. this._orderContent(this.getDrawerPosition());
  323. this._whenPanelRefreshed = new _deferred.Deferred;
  324. this._strategy.renderPanel(this._getTemplate(this.option("template")), this._whenPanelRefreshed);
  325. (0, _window.hasWindow)() && this._whenPanelRefreshed.always(function() {
  326. _this2._strategy.setPanelSize("slide" === _this2.option("revealMode"));
  327. _this2._renderPosition(_this2.option("opened"), false, true)
  328. })
  329. },
  330. _setInitialViewContentPosition: function() {
  331. (0, _renderer2.default)(this.viewContent()).css("paddingLeft", 0);
  332. (0, _renderer2.default)(this.viewContent()).css("left", 0);
  333. (0, _renderer2.default)(this.viewContent()).css("transform", "translate(0px, 0px)")
  334. },
  335. _clean: function() {
  336. this._cleanFocusState();
  337. this._cleanPanel()
  338. },
  339. _cleanPanel: function() {
  340. if (this._$panel) {
  341. this._$panel.remove()
  342. }
  343. if (this._overlay) {
  344. this._overlay.dispose();
  345. delete this._overlay;
  346. delete this._$panel
  347. }
  348. },
  349. _optionChanged: function(args) {
  350. switch (args.name) {
  351. case "width":
  352. this.callBase(args);
  353. this._dimensionChanged();
  354. break;
  355. case "opened":
  356. this._renderPosition(args.value);
  357. this._toggleVisibleClass(args.value);
  358. break;
  359. case "position":
  360. this._refreshPositionClass(args.previousValue);
  361. this._invalidate();
  362. break;
  363. case "contentTemplate":
  364. case "template":
  365. this._invalidate();
  366. break;
  367. case "openedStateMode":
  368. case "target":
  369. this._initStrategy();
  370. this._refreshModeClass(args.previousValue);
  371. this._refreshPanel();
  372. break;
  373. case "minSize":
  374. case "maxSize":
  375. this._initSize();
  376. this._renderPosition(this.option("opened"), false);
  377. break;
  378. case "revealMode":
  379. this._refreshRevealModeClass(args.previousValue);
  380. this._refreshPanel();
  381. break;
  382. case "shading":
  383. this._toggleShaderVisibility(this.option("opened"));
  384. break;
  385. case "animationEnabled":
  386. case "animationDuration":
  387. case "closeOnOutsideClick":
  388. break;
  389. default:
  390. this.callBase(args)
  391. }
  392. },
  393. content: function() {
  394. return (0, _dom.getPublicElement)(this._$panel)
  395. },
  396. viewContent: function() {
  397. return (0, _dom.getPublicElement)(this._$contentWrapper)
  398. },
  399. show: function() {
  400. return this.toggle(true)
  401. },
  402. hide: function() {
  403. return this.toggle(false)
  404. },
  405. toggle: function(showing) {
  406. showing = void 0 === showing ? !this.option("opened") : showing;
  407. this._animationPromise = new _deferred.Deferred;
  408. this.option("opened", showing);
  409. return this._animationPromise.promise()
  410. }
  411. });
  412. (0, _component_registrator2.default)("dxDrawer", Drawer);
  413. module.exports = Drawer;