component.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /**
  2. * DevExtreme (core/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. function _typeof(obj) {
  11. "@babel/helpers - typeof";
  12. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
  13. return typeof obj
  14. } : function(obj) {
  15. return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj
  16. }, _typeof(obj)
  17. }
  18. function _toConsumableArray(arr) {
  19. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread()
  20. }
  21. function _nonIterableSpread() {
  22. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
  23. }
  24. function _unsupportedIterableToArray(o, minLen) {
  25. if (!o) {
  26. return
  27. }
  28. if ("string" === typeof o) {
  29. return _arrayLikeToArray(o, minLen)
  30. }
  31. var n = Object.prototype.toString.call(o).slice(8, -1);
  32. if ("Object" === n && o.constructor) {
  33. n = o.constructor.name
  34. }
  35. if ("Map" === n || "Set" === n) {
  36. return Array.from(o)
  37. }
  38. if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) {
  39. return _arrayLikeToArray(o, minLen)
  40. }
  41. }
  42. function _iterableToArray(iter) {
  43. if ("undefined" !== typeof Symbol && null != iter[Symbol.iterator] || null != iter["@@iterator"]) {
  44. return Array.from(iter)
  45. }
  46. }
  47. function _arrayWithoutHoles(arr) {
  48. if (Array.isArray(arr)) {
  49. return _arrayLikeToArray(arr)
  50. }
  51. }
  52. function _arrayLikeToArray(arr, len) {
  53. if (null == len || len > arr.length) {
  54. len = arr.length
  55. }
  56. for (var i = 0, arr2 = new Array(len); i < len; i++) {
  57. arr2[i] = arr[i]
  58. }
  59. return arr2
  60. }
  61. function _classCallCheck(instance, Constructor) {
  62. if (!(instance instanceof Constructor)) {
  63. throw new TypeError("Cannot call a class as a function")
  64. }
  65. }
  66. function _defineProperties(target, props) {
  67. for (var i = 0; i < props.length; i++) {
  68. var descriptor = props[i];
  69. descriptor.enumerable = descriptor.enumerable || false;
  70. descriptor.configurable = true;
  71. if ("value" in descriptor) {
  72. descriptor.writable = true
  73. }
  74. Object.defineProperty(target, descriptor.key, descriptor)
  75. }
  76. }
  77. function _createClass(Constructor, protoProps, staticProps) {
  78. if (protoProps) {
  79. _defineProperties(Constructor.prototype, protoProps)
  80. }
  81. if (staticProps) {
  82. _defineProperties(Constructor, staticProps)
  83. }
  84. Object.defineProperty(Constructor, "prototype", {
  85. writable: false
  86. });
  87. return Constructor
  88. }
  89. var Config = require("./config");
  90. var domAdapter = require("./dom_adapter");
  91. var extend = require("./utils/extend").extend;
  92. var Class = require("./class");
  93. var Action = require("./action");
  94. var errors = require("./errors");
  95. var coreDataUtils = require("./utils/data");
  96. var commonUtils = require("./utils/common");
  97. var typeUtils = require("./utils/type");
  98. var deferredUtils = require("../core/utils/deferred");
  99. var Deferred = deferredUtils.Deferred;
  100. var when = deferredUtils.when;
  101. var Callbacks = require("./utils/callbacks");
  102. var EventsMixin = require("./events_mixin");
  103. var publicComponentUtils = require("./utils/public_component");
  104. var devices = require("./devices");
  105. var isFunction = typeUtils.isFunction;
  106. var noop = commonUtils.noop;
  107. var cachedGetters = {};
  108. var cachedSetters = {};
  109. var PostponedOperations = function() {
  110. function PostponedOperations() {
  111. _classCallCheck(this, PostponedOperations);
  112. this._postponedOperations = {}
  113. }
  114. _createClass(PostponedOperations, [{
  115. key: "add",
  116. value: function(key, fn, postponedPromise) {
  117. if (key in this._postponedOperations) {
  118. postponedPromise && this._postponedOperations[key].promises.push(postponedPromise)
  119. } else {
  120. var completePromise = new Deferred;
  121. this._postponedOperations[key] = {
  122. fn: fn,
  123. completePromise: completePromise,
  124. promises: postponedPromise ? [postponedPromise] : []
  125. }
  126. }
  127. return this._postponedOperations[key].completePromise.promise()
  128. }
  129. }, {
  130. key: "callPostponedOperations",
  131. value: function() {
  132. for (var key in this._postponedOperations) {
  133. var operation = this._postponedOperations[key];
  134. if (typeUtils.isDefined(operation)) {
  135. if (operation.promises && operation.promises.length) {
  136. when.apply(void 0, _toConsumableArray(operation.promises)).done(operation.fn).then(operation.completePromise.resolve)
  137. } else {
  138. operation.fn().done(operation.completePromise.resolve)
  139. }
  140. }
  141. }
  142. this._postponedOperations = {}
  143. }
  144. }]);
  145. return PostponedOperations
  146. }();
  147. var Component = Class.inherit({
  148. _setDeprecatedOptions: function() {
  149. this._deprecatedOptions = {}
  150. },
  151. _getDeprecatedOptions: function() {
  152. return this._deprecatedOptions
  153. },
  154. _getOptionAliasesByName: function(optionName) {
  155. var _this = this;
  156. return Object.keys(this._deprecatedOptions).filter(function(aliasName) {
  157. return optionName === _this._deprecatedOptions[aliasName].alias
  158. })
  159. },
  160. _getDefaultOptions: function() {
  161. return {
  162. onInitialized: null,
  163. onOptionChanged: null,
  164. onDisposing: null,
  165. defaultOptionsRules: null
  166. }
  167. },
  168. _setDefaultOptions: function() {
  169. this._options = this._getDefaultOptions()
  170. },
  171. _defaultOptionsRules: function() {
  172. return []
  173. },
  174. _setOptionsByDevice: function(customRules) {
  175. var rules = this._defaultOptionsRules();
  176. if (Array.isArray(customRules)) {
  177. rules = rules.concat(customRules)
  178. }
  179. var rulesOptions = this._convertRulesToOptions(rules);
  180. extend(true, this._options, rulesOptions);
  181. for (var fieldName in this._optionsByReference) {
  182. if (Object.prototype.hasOwnProperty.call(rulesOptions, fieldName)) {
  183. this._options[fieldName] = rulesOptions[fieldName]
  184. }
  185. }
  186. },
  187. _convertRulesToOptions: function(rules) {
  188. var options = {};
  189. var currentDevice = devices.current();
  190. var deviceMatch = function(device, filter) {
  191. var filterArray = [];
  192. Array.prototype.push.call(filterArray, filter);
  193. return 1 === filterArray.length && typeUtils.isEmptyObject(filterArray[0]) || commonUtils.findBestMatches(device, filterArray).length > 0
  194. };
  195. for (var i = 0; i < rules.length; i++) {
  196. var rule = rules[i];
  197. var deviceFilter = rule.device || {};
  198. var match;
  199. if (isFunction(deviceFilter)) {
  200. match = deviceFilter(currentDevice)
  201. } else {
  202. match = deviceMatch(currentDevice, deviceFilter)
  203. }
  204. if (match) {
  205. extend(options, rule.options)
  206. }
  207. }
  208. return options
  209. },
  210. _isInitialOptionValue: function(name) {
  211. var optionValue = this.option(name);
  212. var initialOptionValue = this.initialOption(name);
  213. var isInitialOption = isFunction(optionValue) && isFunction(initialOptionValue) ? optionValue.toString() === initialOptionValue.toString() : commonUtils.equalByValue(optionValue, initialOptionValue);
  214. return isInitialOption
  215. },
  216. _setOptionsByReference: function() {
  217. this._optionsByReference = {}
  218. },
  219. _getOptionsByReference: function() {
  220. return this._optionsByReference
  221. },
  222. ctor: function(options) {
  223. this.NAME = publicComponentUtils.name(this.constructor);
  224. options = options || {};
  225. if (options.eventsStrategy) {
  226. this.setEventsStrategy(options.eventsStrategy)
  227. }
  228. this._options = {};
  229. this._updateLockCount = 0;
  230. this._optionChangedCallbacks = options._optionChangedCallbacks || Callbacks();
  231. this._disposingCallbacks = options._disposingCallbacks || Callbacks();
  232. this.postponedOperations = new PostponedOperations;
  233. this.beginUpdate();
  234. try {
  235. this._suppressDeprecatedWarnings();
  236. this._setOptionsByReference();
  237. this._setDeprecatedOptions();
  238. this._setDefaultOptions();
  239. if (options && options.onInitializing) {
  240. options.onInitializing.apply(this, [options])
  241. }
  242. this._setOptionsByDevice(options.defaultOptionsRules);
  243. this._resumeDeprecatedWarnings();
  244. this._initOptions(options)
  245. } finally {
  246. this.endUpdate()
  247. }
  248. },
  249. _initOptions: function(options) {
  250. this.option(options)
  251. },
  252. _optionValuesEqual: function(name, oldValue, newValue) {
  253. oldValue = coreDataUtils.toComparable(oldValue, true);
  254. newValue = coreDataUtils.toComparable(newValue, true);
  255. if (oldValue && newValue && typeUtils.isRenderer(oldValue) && typeUtils.isRenderer(newValue)) {
  256. return newValue.is(oldValue)
  257. }
  258. var oldValueIsNaN = oldValue !== oldValue;
  259. var newValueIsNaN = newValue !== newValue;
  260. if (oldValueIsNaN && newValueIsNaN) {
  261. return true
  262. }
  263. if (null === oldValue || "object" !== _typeof(oldValue) || domAdapter.isElementNode(oldValue)) {
  264. return oldValue === newValue
  265. }
  266. return false
  267. },
  268. _init: function() {
  269. this._createOptionChangedAction();
  270. this.on("disposing", function(args) {
  271. this._disposingCallbacks.fireWith(this, [args])
  272. }.bind(this))
  273. },
  274. _createOptionChangedAction: function() {
  275. this._optionChangedAction = this._createActionByOption("onOptionChanged", {
  276. excludeValidators: ["disabled", "readOnly"]
  277. })
  278. },
  279. _createDisposingAction: function() {
  280. this._disposingAction = this._createActionByOption("onDisposing", {
  281. excludeValidators: ["disabled", "readOnly"]
  282. })
  283. },
  284. _optionChanged: function(args) {
  285. switch (args.name) {
  286. case "onDisposing":
  287. case "onInitialized":
  288. break;
  289. case "onOptionChanged":
  290. this._createOptionChangedAction();
  291. break;
  292. case "defaultOptionsRules":
  293. }
  294. },
  295. _dispose: function() {
  296. this._optionChangedCallbacks.empty();
  297. this._createDisposingAction();
  298. this._disposingAction();
  299. this._disposeEvents();
  300. this._disposed = true
  301. },
  302. instance: function() {
  303. return this
  304. },
  305. beginUpdate: function() {
  306. this._updateLockCount++
  307. },
  308. endUpdate: function() {
  309. this._updateLockCount = Math.max(this._updateLockCount - 1, 0);
  310. if (!this._updateLockCount) {
  311. this.postponedOperations.callPostponedOperations();
  312. if (!this._initializing && !this._initialized) {
  313. this._initializing = true;
  314. try {
  315. this._init()
  316. } finally {
  317. this._initializing = false;
  318. this._updateLockCount++;
  319. this._createActionByOption("onInitialized", {
  320. excludeValidators: ["disabled", "readOnly"]
  321. })();
  322. this._updateLockCount--;
  323. this._initialized = true
  324. }
  325. }
  326. }
  327. },
  328. _logWarningIfDeprecated: function(option) {
  329. var info = this._deprecatedOptions[option];
  330. if (info && !this._deprecatedOptionsSuppressed) {
  331. this._logDeprecatedWarning(option, info)
  332. }
  333. },
  334. _logDeprecatedWarningCount: 0,
  335. _logDeprecatedWarning: function(option, info) {
  336. var message = info.message || "Use the '" + info.alias + "' option instead";
  337. errors.log("W0001", this.NAME, option, info.since, message);
  338. ++this._logDeprecatedWarningCount
  339. },
  340. _suppressDeprecatedWarnings: function() {
  341. this._deprecatedOptionsSuppressed = true
  342. },
  343. _resumeDeprecatedWarnings: function() {
  344. this._deprecatedOptionsSuppressed = false
  345. },
  346. _optionChanging: noop,
  347. _notifyOptionChanged: function(option, value, previousValue) {
  348. var that = this;
  349. if (this._initialized) {
  350. var optionNames = [option].concat(that._getOptionAliasesByName(option));
  351. for (var i = 0; i < optionNames.length; i++) {
  352. var name = optionNames[i];
  353. var args = {
  354. name: name.split(/[.[]/)[0],
  355. fullName: name,
  356. value: value,
  357. previousValue: previousValue
  358. };
  359. that._optionChangedCallbacks.fireWith(that, [extend(that._defaultActionArgs(), args)]);
  360. that._optionChangedAction(extend({}, args));
  361. if (!that._disposed && this._cancelOptionChange !== args.name) {
  362. that._optionChanged(args)
  363. }
  364. }
  365. }
  366. },
  367. initialOption: function(optionName) {
  368. var currentOptions;
  369. var currentInitialized = this._initialized;
  370. if (!this._initialOptions) {
  371. currentOptions = this._options;
  372. this._options = {};
  373. this._initialized = false;
  374. this._setDefaultOptions();
  375. this._setOptionsByDevice(currentOptions.defaultOptionsRules);
  376. this._initialOptions = this._options;
  377. this._options = currentOptions;
  378. this._initialized = currentInitialized
  379. }
  380. return this._initialOptions[optionName]
  381. },
  382. _defaultActionConfig: function() {
  383. return {
  384. context: this,
  385. component: this
  386. }
  387. },
  388. _defaultActionArgs: function() {
  389. return {
  390. component: this
  391. }
  392. },
  393. _createAction: function(actionSource, config) {
  394. var that = this;
  395. var action;
  396. return function(e) {
  397. if (!arguments.length) {
  398. e = {}
  399. }
  400. if (!typeUtils.isPlainObject(e)) {
  401. e = {
  402. actionValue: e
  403. }
  404. }
  405. action = action || new Action(actionSource, extend(config, that._defaultActionConfig()));
  406. return action.execute.call(action, extend(e, that._defaultActionArgs()))
  407. }
  408. },
  409. _createActionByOption: function(optionName, config) {
  410. var that = this;
  411. var action;
  412. var eventName;
  413. var actionFunc;
  414. var result = function() {
  415. if (!eventName) {
  416. config = config || {};
  417. if ("string" !== typeof optionName) {
  418. throw errors.Error("E0008")
  419. }
  420. if (0 === optionName.indexOf("on")) {
  421. eventName = that._getEventName(optionName)
  422. }
  423. actionFunc = that.option(optionName)
  424. }
  425. if (!action && !actionFunc && !config.beforeExecute && !config.afterExecute && !that.hasEvent(eventName)) {
  426. return
  427. }
  428. if (!action) {
  429. var beforeExecute = config.beforeExecute;
  430. config.beforeExecute = function(args) {
  431. beforeExecute && beforeExecute.apply(that, arguments);
  432. that.fireEvent(eventName, args.args)
  433. };
  434. that._suppressDeprecatedWarnings();
  435. action = that._createAction(actionFunc, config);
  436. that._resumeDeprecatedWarnings()
  437. }
  438. if (Config().wrapActionsBeforeExecute) {
  439. var beforeActionExecute = that.option("beforeActionExecute") || noop;
  440. var wrappedAction = beforeActionExecute(that, action, config) || action;
  441. return wrappedAction.apply(that, arguments)
  442. }
  443. return action.apply(that, arguments)
  444. };
  445. if (!Config().wrapActionsBeforeExecute) {
  446. var onActionCreated = that.option("onActionCreated") || noop;
  447. result = onActionCreated(that, result, config) || result
  448. }
  449. return result
  450. },
  451. _getEventName: function(actionName) {
  452. return actionName.charAt(2).toLowerCase() + actionName.substr(3)
  453. },
  454. hasActionSubscription: function(actionName) {
  455. return !!this.option(actionName) || this.hasEvent(this._getEventName(actionName))
  456. },
  457. isOptionDeprecated: function(name) {
  458. var deprecatedOptions = this._getDeprecatedOptions();
  459. return Object.prototype.hasOwnProperty.call(deprecatedOptions, name)
  460. },
  461. _setOptionSilent: function(name, value) {
  462. this._cancelOptionChange = name;
  463. this.option(name, value);
  464. this._cancelOptionChange = false
  465. },
  466. option: function() {
  467. var normalizeOptionName = function(that, name) {
  468. var deprecate;
  469. if (name) {
  470. if (!that._cachedDeprecateNames) {
  471. that._cachedDeprecateNames = [];
  472. for (var optionName in that._deprecatedOptions) {
  473. that._cachedDeprecateNames.push(optionName)
  474. }
  475. }
  476. for (var i = 0; i < that._cachedDeprecateNames.length; i++) {
  477. if (that._cachedDeprecateNames[i] === name) {
  478. deprecate = that._deprecatedOptions[name];
  479. break
  480. }
  481. }
  482. if (deprecate) {
  483. that._logWarningIfDeprecated(name);
  484. var alias = deprecate.alias;
  485. if (alias) {
  486. name = alias
  487. }
  488. }
  489. }
  490. return name
  491. };
  492. var getPreviousName = function(fullName) {
  493. var splitNames = fullName.split(".");
  494. splitNames.pop();
  495. return splitNames.join(".")
  496. };
  497. var getFieldName = function(fullName) {
  498. var splitNames = fullName.split(".");
  499. return splitNames[splitNames.length - 1]
  500. };
  501. var getOptionValue = function(options, name, unwrapObservables) {
  502. var getter = cachedGetters[name];
  503. if (!getter) {
  504. getter = cachedGetters[name] = coreDataUtils.compileGetter(name)
  505. }
  506. return getter(options, {
  507. functionsAsIs: true,
  508. unwrapObservables: unwrapObservables
  509. })
  510. };
  511. var clearOptionsField = function(options, name) {
  512. delete options[name];
  513. var previousFieldName = getPreviousName(name);
  514. var fieldName = getFieldName(name);
  515. var fieldObject = previousFieldName ? getOptionValue(options, previousFieldName, false) : options;
  516. if (fieldObject) {
  517. delete fieldObject[fieldName]
  518. }
  519. };
  520. var setOptionsField = function(options, fullName, value) {
  521. var fieldName = "";
  522. var fieldObject;
  523. do {
  524. if (fieldName) {
  525. fieldName = "." + fieldName
  526. }
  527. fieldName = getFieldName(fullName) + fieldName;
  528. fullName = getPreviousName(fullName);
  529. fieldObject = fullName ? getOptionValue(options, fullName, false) : options
  530. } while (!fieldObject);
  531. fieldObject[fieldName] = value
  532. };
  533. var normalizeOptionValue = function(that, options, name, value) {
  534. if (name) {
  535. var alias = normalizeOptionName(that, name);
  536. if (alias && alias !== name) {
  537. setOptionsField(options, alias, value);
  538. clearOptionsField(options, name)
  539. }
  540. }
  541. };
  542. var prepareOption = function prepareOption(that, options, name, value) {
  543. if (typeUtils.isPlainObject(value)) {
  544. for (var valueName in value) {
  545. prepareOption(that, options, name + "." + valueName, value[valueName])
  546. }
  547. }
  548. normalizeOptionValue(that, options, name, value)
  549. };
  550. var setOptionValue = function(that, name, value) {
  551. if (!cachedSetters[name]) {
  552. cachedSetters[name] = coreDataUtils.compileSetter(name)
  553. }
  554. var path = name.split(/[.[]/);
  555. cachedSetters[name](that._options, value, {
  556. functionsAsIs: true,
  557. merge: !that._getOptionsByReference()[name],
  558. unwrapObservables: path.length > 1 && !!that._getOptionsByReference()[path[0]]
  559. })
  560. };
  561. var setOption = function(that, name, value) {
  562. var previousValue = getOptionValue(that._options, name, false);
  563. if (that._optionValuesEqual(name, previousValue, value)) {
  564. return
  565. }
  566. if (that._initialized) {
  567. that._optionChanging(name, previousValue, value)
  568. }
  569. setOptionValue(that, name, value);
  570. that._notifyOptionChanged(name, value, previousValue)
  571. };
  572. return function(options, value) {
  573. var that = this;
  574. var name = options;
  575. if (arguments.length < 2 && "object" !== typeUtils.type(name)) {
  576. name = normalizeOptionName(that, name);
  577. return getOptionValue(that._options, name)
  578. }
  579. if ("string" === typeof name) {
  580. options = {};
  581. options[name] = value
  582. }
  583. that.beginUpdate();
  584. try {
  585. var optionName;
  586. for (optionName in options) {
  587. prepareOption(that, options, optionName, options[optionName])
  588. }
  589. for (optionName in options) {
  590. setOption(that, optionName, options[optionName])
  591. }
  592. } finally {
  593. that.endUpdate()
  594. }
  595. }
  596. }(),
  597. _getOptionValue: function(name, context) {
  598. var value = this.option(name);
  599. if (isFunction(value)) {
  600. return value.bind(context)()
  601. }
  602. return value
  603. }
  604. }).include(EventsMixin);
  605. module.exports = Component;
  606. module.exports.PostponedOperations = PostponedOperations;