dom_component.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /**
  2. * DevExtreme (core/dom_component.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 _window = require("../core/utils/window");
  15. var _window2 = _interopRequireDefault(_window);
  16. var _extend = require("./utils/extend");
  17. var _config = require("./config");
  18. var _config2 = _interopRequireDefault(_config);
  19. var _errors = require("./errors");
  20. var _errors2 = _interopRequireDefault(_errors);
  21. var _dom = require("../core/utils/dom");
  22. var _resize_callbacks = require("../core/utils/resize_callbacks");
  23. var _resize_callbacks2 = _interopRequireDefault(_resize_callbacks);
  24. var _common = require("./utils/common");
  25. var _common2 = _interopRequireDefault(_common);
  26. var _iterator = require("./utils/iterator");
  27. var _type = require("./utils/type");
  28. var _array = require("./utils/array");
  29. var _public_component = require("./utils/public_component");
  30. var _public_component2 = _interopRequireDefault(_public_component);
  31. var _element_data = require("./element_data");
  32. var _element_data2 = _interopRequireDefault(_element_data);
  33. var _component = require("./component");
  34. var _component2 = _interopRequireDefault(_component);
  35. function _interopRequireDefault(obj) {
  36. return obj && obj.__esModule ? obj : {
  37. "default": obj
  38. }
  39. }
  40. var abstract = _component2.default.abstract;
  41. var RTL_DIRECTION_CLASS = "dx-rtl";
  42. var VISIBILITY_CHANGE_CLASS = "dx-visibility-change-handler";
  43. var VISIBILITY_CHANGE_EVENTNAMESPACE = "VisibilityChange";
  44. var DOMComponent = _component2.default.inherit({
  45. _getDefaultOptions: function() {
  46. return (0, _extend.extend)(this.callBase(), {
  47. width: void 0,
  48. height: void 0,
  49. rtlEnabled: (0, _config2.default)().rtlEnabled,
  50. elementAttr: {},
  51. disabled: false,
  52. integrationOptions: {}
  53. })
  54. },
  55. ctor: function(element, options) {
  56. this._$element = (0, _renderer2.default)(element);
  57. _public_component2.default.attachInstanceToElement(this._$element, this, this._dispose);
  58. this.callBase(options)
  59. },
  60. _getSynchronizableOptionsForCreateComponent: function() {
  61. return ["rtlEnabled", "disabled", "templatesRenderAsynchronously"]
  62. },
  63. _visibilityChanged: abstract,
  64. _dimensionChanged: abstract,
  65. _init: function() {
  66. this.callBase();
  67. this._attachWindowResizeCallback()
  68. },
  69. _setOptionsByDevice: function(instanceCustomRules) {
  70. this.callBase([].concat(this.constructor._classCustomRules || [], instanceCustomRules || []))
  71. },
  72. _isInitialOptionValue: function(name) {
  73. var isCustomOption = this.constructor._classCustomRules && Object.prototype.hasOwnProperty.call(this._convertRulesToOptions(this.constructor._classCustomRules), name);
  74. return !isCustomOption && this.callBase(name)
  75. },
  76. _attachWindowResizeCallback: function() {
  77. if (this._isDimensionChangeSupported()) {
  78. var windowResizeCallBack = this._windowResizeCallBack = this._dimensionChanged.bind(this);
  79. _resize_callbacks2.default.add(windowResizeCallBack)
  80. }
  81. },
  82. _isDimensionChangeSupported: function() {
  83. return this._dimensionChanged !== abstract
  84. },
  85. _renderComponent: function() {
  86. this._initMarkup();
  87. if (_window2.default.hasWindow()) {
  88. this._render()
  89. }
  90. },
  91. _initMarkup: function() {
  92. this._renderElementAttributes();
  93. this._toggleRTLDirection(this.option("rtlEnabled"));
  94. this._renderVisibilityChange();
  95. this._renderDimensions()
  96. },
  97. _render: function() {
  98. this._attachVisibilityChangeHandlers()
  99. },
  100. _renderElementAttributes: function() {
  101. var attributes = (0, _extend.extend)({}, this.option("elementAttr"));
  102. var classNames = attributes.class;
  103. delete attributes.class;
  104. this.$element().attr(attributes).addClass(classNames)
  105. },
  106. _renderVisibilityChange: function() {
  107. if (this._isDimensionChangeSupported()) {
  108. this._attachDimensionChangeHandlers()
  109. }
  110. if (!this._isVisibilityChangeSupported()) {
  111. return
  112. }
  113. this.$element().addClass(VISIBILITY_CHANGE_CLASS)
  114. },
  115. _renderDimensions: function() {
  116. var $element = this.$element();
  117. var element = $element.get(0);
  118. var width = this._getOptionValue("width", element);
  119. var height = this._getOptionValue("height", element);
  120. if (this._isCssUpdateRequired(element, height, width)) {
  121. $element.css({
  122. width: null === width ? "" : width,
  123. height: null === height ? "" : height
  124. })
  125. }
  126. },
  127. _isCssUpdateRequired: function(element, height, width) {
  128. return !!((0, _type.isDefined)(width) || (0, _type.isDefined)(height) || element.style.width || element.style.height)
  129. },
  130. _attachDimensionChangeHandlers: function() {
  131. var that = this;
  132. var resizeEventName = "dxresize." + this.NAME + VISIBILITY_CHANGE_EVENTNAMESPACE;
  133. _events_engine2.default.off(that.$element(), resizeEventName);
  134. _events_engine2.default.on(that.$element(), resizeEventName, function() {
  135. that._dimensionChanged()
  136. })
  137. },
  138. _attachVisibilityChangeHandlers: function() {
  139. if (!this._isVisibilityChangeSupported()) {
  140. return
  141. }
  142. var that = this;
  143. var hidingEventName = "dxhiding." + this.NAME + VISIBILITY_CHANGE_EVENTNAMESPACE;
  144. var shownEventName = "dxshown." + this.NAME + VISIBILITY_CHANGE_EVENTNAMESPACE;
  145. that._isHidden = !that._isVisible();
  146. _events_engine2.default.off(that.$element(), hidingEventName);
  147. _events_engine2.default.on(that.$element(), hidingEventName, function() {
  148. that._checkVisibilityChanged("hiding")
  149. });
  150. _events_engine2.default.off(that.$element(), shownEventName);
  151. _events_engine2.default.on(that.$element(), shownEventName, function() {
  152. that._checkVisibilityChanged("shown")
  153. })
  154. },
  155. _isVisible: function() {
  156. return this.$element().is(":visible")
  157. },
  158. _checkVisibilityChanged: function(event) {
  159. if ("hiding" === event && this._isVisible() && !this._isHidden) {
  160. this._visibilityChanged(false);
  161. this._isHidden = true
  162. } else {
  163. if ("shown" === event && this._isVisible() && this._isHidden) {
  164. this._isHidden = false;
  165. this._visibilityChanged(true)
  166. }
  167. }
  168. },
  169. _isVisibilityChangeSupported: function() {
  170. return this._visibilityChanged !== abstract && _window2.default.hasWindow()
  171. },
  172. _clean: _common2.default.noop,
  173. _modelByElement: function() {
  174. var modelByElement = this.option("modelByElement") || _common2.default.noop;
  175. return modelByElement(this.$element())
  176. },
  177. _invalidate: function() {
  178. if (!this._updateLockCount) {
  179. throw _errors2.default.Error("E0007")
  180. }
  181. this._requireRefresh = true
  182. },
  183. _refresh: function() {
  184. this._clean();
  185. this._renderComponent()
  186. },
  187. _dispose: function() {
  188. this.callBase();
  189. this._clean();
  190. this._detachWindowResizeCallback()
  191. },
  192. _detachWindowResizeCallback: function() {
  193. if (this._isDimensionChangeSupported()) {
  194. _resize_callbacks2.default.remove(this._windowResizeCallBack)
  195. }
  196. },
  197. _toggleRTLDirection: function(rtl) {
  198. this.$element().toggleClass(RTL_DIRECTION_CLASS, rtl)
  199. },
  200. _createComponent: function(element, component, config) {
  201. var _this = this;
  202. var that = this;
  203. config = config || {};
  204. var synchronizableOptions = _common2.default.grep(this._getSynchronizableOptionsForCreateComponent(), function(value) {
  205. return !(value in config)
  206. });
  207. var nestedComponentOptions = that.option("nestedComponentOptions") || _common2.default.noop;
  208. var nestedComponentConfig = (0, _extend.extend)({
  209. integrationOptions: this.option("integrationOptions")
  210. }, nestedComponentOptions(this));
  211. synchronizableOptions.forEach(function(optionName) {
  212. nestedComponentConfig[optionName] = _this.option(optionName)
  213. });
  214. that._extendConfig(config, nestedComponentConfig);
  215. var instance;
  216. if ((0, _type.isString)(component)) {
  217. var $element = (0, _renderer2.default)(element)[component](config);
  218. instance = $element[component]("instance")
  219. } else {
  220. if (element) {
  221. instance = component.getInstance(element);
  222. if (instance) {
  223. instance.option(config)
  224. } else {
  225. instance = new component(element, config)
  226. }
  227. }
  228. }
  229. if (instance) {
  230. var optionChangedHandler = function(args) {
  231. if ((0, _array.inArray)(args.name, synchronizableOptions) >= 0) {
  232. instance.option(args.name, args.value)
  233. }
  234. };
  235. that.on("optionChanged", optionChangedHandler);
  236. instance.on("disposing", function() {
  237. that.off("optionChanged", optionChangedHandler)
  238. })
  239. }
  240. return instance
  241. },
  242. _extendConfig: function(config, extendConfig) {
  243. (0, _iterator.each)(extendConfig, function(key, value) {
  244. config[key] = Object.prototype.hasOwnProperty.call(config, key) ? config[key] : value
  245. })
  246. },
  247. _defaultActionConfig: function() {
  248. return (0, _extend.extend)(this.callBase(), {
  249. context: this._modelByElement(this.$element())
  250. })
  251. },
  252. _defaultActionArgs: function() {
  253. var model = this._modelByElement(this.$element());
  254. return (0, _extend.extend)(this.callBase(), {
  255. element: this.element(),
  256. model: model
  257. })
  258. },
  259. _optionChanged: function(args) {
  260. switch (args.name) {
  261. case "width":
  262. case "height":
  263. this._renderDimensions();
  264. break;
  265. case "rtlEnabled":
  266. this._invalidate();
  267. break;
  268. case "elementAttr":
  269. this._renderElementAttributes();
  270. break;
  271. case "disabled":
  272. case "integrationOptions":
  273. break;
  274. default:
  275. this.callBase(args)
  276. }
  277. },
  278. _removeAttributes: function(element) {
  279. var i = element.attributes.length - 1;
  280. for (; i >= 0; i--) {
  281. var attribute = element.attributes[i];
  282. if (!attribute) {
  283. return
  284. }
  285. var attributeName = attribute.name;
  286. if (0 === attributeName.indexOf("aria-") || attributeName.indexOf("dx-") !== -1 || "role" === attributeName || "style" === attributeName || "tabindex" === attributeName) {
  287. element.removeAttribute(attributeName)
  288. }
  289. }
  290. },
  291. _removeClasses: function(element) {
  292. var classes = element.className.split(" ").filter(function(cssClass) {
  293. return 0 !== cssClass.lastIndexOf("dx-", 0)
  294. });
  295. element.className = classes.join(" ")
  296. },
  297. endUpdate: function() {
  298. var requireRender = !this._initializing && !this._initialized;
  299. this.callBase.apply(this, arguments);
  300. if (!this._updateLockCount) {
  301. if (requireRender) {
  302. this._renderComponent()
  303. } else {
  304. if (this._requireRefresh) {
  305. this._requireRefresh = false;
  306. this._refresh()
  307. }
  308. }
  309. }
  310. },
  311. $element: function() {
  312. return this._$element
  313. },
  314. element: function() {
  315. return (0, _dom.getPublicElement)(this.$element())
  316. },
  317. dispose: function() {
  318. var element = this.$element().get(0);
  319. _element_data2.default.cleanDataRecursive(element, true);
  320. element.textContent = "";
  321. this._removeAttributes(element);
  322. this._removeClasses(element)
  323. }
  324. });
  325. DOMComponent.getInstance = function(element) {
  326. return _public_component2.default.getInstanceByElement((0, _renderer2.default)(element), this)
  327. };
  328. DOMComponent.defaultOptions = function(rule) {
  329. this._classCustomRules = this._classCustomRules || [];
  330. this._classCustomRules.push(rule)
  331. };
  332. module.exports = DOMComponent;
  333. module.exports.default = module.exports;