devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
346 lines (345 loc) • 12.5 kB
JavaScript
/**
* DevExtreme (esm/__internal/core/widget/component.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import Action from "../../../core/action";
import Class from "../../../core/class";
import Config from "../../../core/config";
import errors from "../../../core/errors";
import {
EventsStrategy
} from "../../../core/events_strategy";
import {
Options
} from "../../../core/options/index";
import {
convertRulesToOptions
} from "../../../core/options/utils";
import {
PostponedOperations
} from "../../../core/postponed_operations";
import Callbacks from "../../../core/utils/callbacks";
import {
noop
} from "../../../core/utils/common";
import {
getPathParts
} from "../../../core/utils/data";
import {
extend
} from "../../../core/utils/extend";
import {
name as publicComponentName
} from "../../../core/utils/public_component";
import {
isDefined,
isFunction,
isPlainObject
} from "../../../core/utils/type";
const getEventName = actionName => actionName.charAt(2).toLowerCase() + actionName.substr(3);
const isInnerOption = optionName => 0 === optionName.indexOf("_", 0);
export class Component extends(Class.inherit({})) {
_setDeprecatedOptions() {
this._deprecatedOptions = {}
}
_getDeprecatedOptions() {
return this._deprecatedOptions
}
_getDefaultOptions() {
return {
onInitialized: null,
onOptionChanged: null,
onDisposing: null,
defaultOptionsRules: null
}
}
_defaultOptionsRules() {
return []
}
_setOptionsByDevice(rules) {
this._options.applyRules(rules)
}
_convertRulesToOptions(rules) {
return convertRulesToOptions(rules)
}
_isInitialOptionValue(name) {
return this._options.isInitial(name)
}
_setOptionsByReference() {
this._optionsByReference = {}
}
_getOptionsByReference() {
return this._optionsByReference
}
ctor() {
let options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
const {
_optionChangedCallbacks: _optionChangedCallbacks,
_disposingCallbacks: _disposingCallbacks
} = options;
this.NAME = publicComponentName(this.constructor);
this._eventsStrategy = EventsStrategy.create(this, options.eventsStrategy);
this._updateLockCount = 0;
this._optionChangedCallbacks = _optionChangedCallbacks || Callbacks();
this._disposingCallbacks = _disposingCallbacks || Callbacks();
this.postponedOperations = new PostponedOperations;
this._createOptions(options)
}
_createOptions(options) {
this.beginUpdate();
try {
this._setOptionsByReference();
this._setDeprecatedOptions();
this._options = new Options(this._getDefaultOptions(), this._getDefaultOptions(), this._getOptionsByReference(), this._getDeprecatedOptions());
this._options.onChanging(((name, previousValue, value) => this._initialized && this._optionChanging(name, previousValue, value)));
this._options.onDeprecated(((option, info) => this._logDeprecatedOptionWarning(option, info)));
this._options.onChanged(((name, value, previousValue) => this._notifyOptionChanged(name, value, previousValue)));
this._options.onStartChange((() => this.beginUpdate()));
this._options.onEndChange((() => this.endUpdate()));
this._options.addRules(this._defaultOptionsRules());
this._options.validateOptions((o => this._validateOptions(o)));
if (options && options.onInitializing) {
options.onInitializing.apply(this, [options])
}
this._setOptionsByDevice(options.defaultOptionsRules);
this._initOptions(options)
} finally {
this.endUpdate()
}
}
_initOptions(options) {
this.option(options)
}
_init() {
this._createOptionChangedAction();
this.on("disposing", (args => {
this._disposingCallbacks.fireWith(this, [args])
}))
}
_logDeprecatedOptionWarning(option, info) {
const message = info.message || `Use the '${info.alias}' option instead`;
errors.log("W0001", this.NAME, option, info.since, message)
}
_logDeprecatedComponentWarning(since, alias) {
errors.log("W0000", this.NAME, since, `Use the '${alias}' widget instead`)
}
_createOptionChangedAction() {
this._optionChangedAction = this._createActionByOption("onOptionChanged", {
excludeValidators: ["disabled", "readOnly"]
})
}
_createDisposingAction() {
this._disposingAction = this._createActionByOption("onDisposing", {
excludeValidators: ["disabled", "readOnly"]
})
}
_optionChanged(args) {
const {
name: name
} = args;
switch (name) {
case "onDisposing":
case "onInitialized":
case "defaultOptionsRules":
default:
break;
case "onOptionChanged":
this._createOptionChangedAction()
}
}
_dispose() {
var _this$_disposingActio;
this._optionChangedCallbacks.empty();
this._createDisposingAction();
null === (_this$_disposingActio = this._disposingAction) || void 0 === _this$_disposingActio || _this$_disposingActio.call(this);
this._eventsStrategy.dispose();
this._options.dispose();
this._disposed = true
}
_lockUpdate() {
this._updateLockCount++
}
_unlockUpdate() {
this._updateLockCount = Math.max(this._updateLockCount - 1, 0)
}
_isUpdateAllowed() {
return 0 === this._updateLockCount
}
_isInitializingRequired() {
return !this._initializing && !this._initialized
}
isInitialized() {
return this._initialized
}
_commitUpdate() {
this.postponedOperations.callPostponedOperations();
this._isInitializingRequired() && this._initializeComponent()
}
_initializeComponent() {
this._initializing = true;
try {
this._init()
} finally {
this._initializing = false;
this._lockUpdate();
this._createActionByOption("onInitialized", {
excludeValidators: ["disabled", "readOnly"]
})();
this._unlockUpdate();
this._initialized = true
}
}
instance() {
return this
}
beginUpdate() {
this._lockUpdate()
}
endUpdate() {
this._unlockUpdate();
this._isUpdateAllowed() && this._commitUpdate()
}
_optionChanging() {}
_notifyOptionChanged(option, value, previousValue) {
if (this._initialized) {
const optionNames = [option].concat(this._options.getAliasesByName(option));
for (let i = 0; i < optionNames.length; i++) {
const name = optionNames[i];
const args = {
name: getPathParts(name)[0],
fullName: name,
value: value,
previousValue: previousValue
};
if (!isInnerOption(name)) {
var _this$_optionChangedA;
this._optionChangedCallbacks.fireWith(this, [extend(this._defaultActionArgs(), args)]);
null === (_this$_optionChangedA = this._optionChangedAction) || void 0 === _this$_optionChangedA || _this$_optionChangedA.call(this, extend({}, args))
}
if (!this._disposed && this._cancelOptionChange !== name) {
this._optionChanged(args)
}
}
}
}
initialOption(name) {
return this._options.initial(name)
}
_defaultActionConfig() {
return {
context: this,
component: this
}
}
_defaultActionArgs() {
return {
component: this
}
}
_createAction(actionSource, config) {
let action;
return e => {
if (!isDefined(e)) {
e = {}
}
if (!isPlainObject(e)) {
e = {
actionValue: e
}
}
action = action || new Action(actionSource, extend({}, config, this._defaultActionConfig()));
return action.execute.call(action, extend(e, this._defaultActionArgs()))
}
}
_createActionByOption(optionName, config) {
var _this = this;
let action;
let eventName;
let actionFunc;
config = extend({}, config);
const result = function() {
var _config, _config2;
if (!eventName) {
config = config || {};
if ("string" !== typeof optionName) {
throw errors.Error("E0008")
}
if (optionName.startsWith("on")) {
eventName = getEventName(optionName)
}
actionFunc = _this.option(optionName)
}
if (!action && !actionFunc && !(null !== (_config = config) && void 0 !== _config && _config.beforeExecute) && !(null !== (_config2 = config) && void 0 !== _config2 && _config2.afterExecute) && !_this._eventsStrategy.hasEvent(eventName)) {
return
}
if (!action) {
const {
beforeExecute: beforeExecute
} = config;
config.beforeExecute = function() {
for (var _len2 = arguments.length, props = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
props[_key2] = arguments[_key2]
}
beforeExecute && beforeExecute.apply(_this, props);
_this._eventsStrategy.fireEvent(eventName, props[0].args)
};
action = _this._createAction(actionFunc, config)
}
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key]
}
if (Config().wrapActionsBeforeExecute) {
const beforeActionExecute = _this.option("beforeActionExecute") || noop;
const wrappedAction = beforeActionExecute(_this, action, config) || action;
return wrappedAction.apply(_this, args)
}
return action.apply(_this, args)
};
if (Config().wrapActionsBeforeExecute) {
return result
}
const onActionCreated = this.option("onActionCreated") || noop;
return onActionCreated(this, result, config) || result
}
on(eventName, eventHandler) {
this._eventsStrategy.on(eventName, eventHandler);
return this
}
off(eventName, eventHandler) {
this._eventsStrategy.off(eventName, eventHandler);
return this
}
hasActionSubscription(actionName) {
return !!this._options.silent(actionName) || this._eventsStrategy.hasEvent(getEventName(actionName))
}
isOptionDeprecated(name) {
return this._options.isDeprecated(name)
}
_setOptionWithoutOptionChange(name, value) {
this._cancelOptionChange = name;
this.option(name, value);
this._cancelOptionChange = false
}
_getOptionValue(name, context) {
const value = this.option(name);
if (isFunction(value)) {
return value.bind(context)()
}
return value
}
option() {
return this._options.option(...arguments)
}
resetOption(name) {
this.beginUpdate();
this._options.reset(name);
this.endUpdate()
}
_validateOptions(options) {
return options
}
}