devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
463 lines (459 loc) • 18 kB
JavaScript
/**
* DevExtreme (cjs/__internal/core/widget/dom_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/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _short = require("../../../common/core/events/short");
var _config = _interopRequireDefault(require("../../../core/config"));
var _element = require("../../../core/element");
var _element_data = require("../../../core/element_data");
var _errors = _interopRequireDefault(require("../../../core/errors"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _common = require("../../../core/utils/common");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _public_component = require("../../../core/utils/public_component");
var _resize_callbacks = _interopRequireDefault(require("../../../core/utils/resize_callbacks"));
var _shadow_dom = require("../../../core/utils/shadow_dom");
var _type = require("../../../core/utils/type");
var _window = require("../../../core/utils/window");
var _license_validation = _interopRequireWildcard(require("../../core/license/license_validation"));
var _m_template_manager = _interopRequireDefault(require("../../core/m_template_manager"));
var _m_common = require("../../core/utils/m_common");
var _component = require("./component");
function _getRequireWildcardCache(e) {
if ("function" != typeof WeakMap) {
return null
}
var r = new WeakMap,
t = new WeakMap;
return (_getRequireWildcardCache = function(e) {
return e ? t : r
})(e)
}
function _interopRequireWildcard(e, r) {
if (!r && e && e.__esModule) {
return e
}
if (null === e || "object" != typeof e && "function" != typeof e) {
return {
default: e
}
}
var t = _getRequireWildcardCache(r);
if (t && t.has(e)) {
return t.get(e)
}
var n = {
__proto__: null
},
a = Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var u in e) {
if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]
}
}
return n.default = e, t && t.set(e, n), n
}
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
class DOMComponent extends _component.Component {
static getInstance(element) {
return (0, _public_component.getInstanceByElement)((0, _renderer.default)(element), this)
}
static defaultOptions(rule) {
this._classCustomRules = Object.hasOwnProperty.bind(this)("_classCustomRules") && this._classCustomRules ? this._classCustomRules : [];
this._classCustomRules.push(rule)
}
_getDefaultOptions() {
return (0, _extend.extend)(super._getDefaultOptions(), {
width: void 0,
height: void 0,
rtlEnabled: (0, _config.default)().rtlEnabled,
elementAttr: {},
disabled: false,
integrationOptions: {}
}, this._useTemplates() ? _m_template_manager.default.TemplateManager.createDefaultOptions() : {})
}
ctor(element, options) {
this._customClass = null;
this._createElement(element);
(0, _public_component.attachInstanceToElement)(this._$element, this, this._dispose);
super.ctor(options);
const validationAlreadyPerformed = (0, _license_validation.peekValidationPerformed)();
_license_validation.default.validateLicense((0, _config.default)().licenseKey);
if (!validationAlreadyPerformed && (0, _license_validation.peekValidationPerformed)()) {
(0, _config.default)({
licenseKey: ""
})
}
_m_common.uiLayerInitialized.resolve()
}
_createElement(element) {
this._$element = (0, _renderer.default)(element)
}
_getSynchronizableOptionsForCreateComponent() {
return ["rtlEnabled", "disabled", "templatesRenderAsynchronously"]
}
_checkFunctionValueDeprecation(optionNames) {
if (!this.option("_ignoreFunctionValueDeprecation")) {
optionNames.forEach((optionName => {
if ((0, _type.isFunction)(this.option(optionName))) {
_errors.default.log("W0017", optionName)
}
}))
}
}
_visibilityChanged(value) {}
_dimensionChanged() {}
_init() {
super._init();
this._checkFunctionValueDeprecation(["width", "height", "maxHeight", "maxWidth", "minHeight", "minWidth", "popupHeight", "popupWidth"]);
this._attachWindowResizeCallback();
this._initTemplateManager()
}
_setOptionsByDevice(instanceCustomRules) {
super._setOptionsByDevice([].concat(this.constructor._classCustomRules || [], instanceCustomRules || []))
}
_isInitialOptionValue(name) {
const isCustomOption = this.constructor._classCustomRules && Object.prototype.hasOwnProperty.call(this._convertRulesToOptions(this.constructor._classCustomRules), name);
return !isCustomOption && super._isInitialOptionValue(name)
}
_attachWindowResizeCallback() {
if (this._isDimensionChangeSupported()) {
const windowResizeCallBack = this._windowResizeCallBack = this._dimensionChanged.bind(this);
_resize_callbacks.default.add(windowResizeCallBack)
}
}
_isDimensionChangeSupported() {
return this._dimensionChanged !== DOMComponent.prototype._dimensionChanged
}
_renderComponent() {
(0, _shadow_dom.addShadowDomStyles)(this.$element());
this._initMarkup();
(0, _window.hasWindow)() && this._render()
}
_initMarkup() {
const {
rtlEnabled: rtlEnabled
} = this.option() || {};
this._renderElementAttributes();
this._toggleRTLDirection(rtlEnabled);
this._renderVisibilityChange();
this._renderDimensions()
}
_render() {
this._attachVisibilityChangeHandlers()
}
_renderElementAttributes() {
const {
elementAttr: elementAttr
} = this.option() || {};
const attributes = (0, _extend.extend)({}, elementAttr);
const classNames = attributes.class;
delete attributes.class;
this.$element().attr(attributes).removeClass(this._customClass).addClass(classNames);
this._customClass = classNames
}
_renderVisibilityChange() {
if (this._isDimensionChangeSupported()) {
this._attachDimensionChangeHandlers()
}
if (this._isVisibilityChangeSupported()) {
const $element = this.$element();
$element.addClass("dx-visibility-change-handler")
}
}
_renderDimensions() {
const $element = this.$element();
const element = $element.get(0);
const width = this._getOptionValue("width", element);
const height = this._getOptionValue("height", element);
if (this._isCssUpdateRequired(element, height, width)) {
$element.css({
width: null === width ? "" : width,
height: null === height ? "" : height
})
}
}
_isCssUpdateRequired(element, height, width) {
return !!((0, _type.isDefined)(width) || (0, _type.isDefined)(height) || element.style.width || element.style.height)
}
_attachDimensionChangeHandlers() {
const $el = this.$element();
const namespace = `${this.NAME}VisibilityChange`;
_short.resize.off($el, {
namespace: namespace
});
_short.resize.on($el, (() => this._dimensionChanged()), {
namespace: namespace
})
}
_attachVisibilityChangeHandlers() {
if (this._isVisibilityChangeSupported()) {
const $el = this.$element();
const namespace = `${this.NAME}VisibilityChange`;
this._isHidden = !this._isVisible();
_short.visibility.off($el, {
namespace: namespace
});
_short.visibility.on($el, (() => this._checkVisibilityChanged("shown")), (() => this._checkVisibilityChanged("hiding")), {
namespace: namespace
})
}
}
_isVisible() {
const $element = this.$element();
return $element.is(":visible")
}
_checkVisibilityChanged(action) {
const isVisible = this._isVisible();
if (isVisible) {
if ("hiding" === action && !this._isHidden) {
this._visibilityChanged(false);
this._isHidden = true
} else if ("shown" === action && this._isHidden) {
this._isHidden = false;
this._visibilityChanged(true)
}
}
}
_isVisibilityChangeSupported() {
return this._visibilityChanged !== DOMComponent.prototype._visibilityChanged && (0, _window.hasWindow)()
}
_clean() {}
_modelByElement(element) {
const {
modelByElement: modelByElement
} = this.option();
const $element = this.$element();
return modelByElement ? modelByElement($element) : void 0
}
_invalidate() {
if (this._isUpdateAllowed()) {
throw _errors.default.Error("E0007")
}
this._requireRefresh = true
}
_refresh() {
this._clean();
this._renderComponent()
}
_dispose() {
this._templateManager && this._templateManager.dispose();
super._dispose();
this._clean();
this._detachWindowResizeCallback()
}
_detachWindowResizeCallback() {
if (this._isDimensionChangeSupported()) {
_resize_callbacks.default.remove(this._windowResizeCallBack)
}
}
_toggleRTLDirection(rtl) {
const $element = this.$element();
$element.toggleClass("dx-rtl", rtl)
}
_createComponent(element, component, componentConfiguration) {
const configuration = componentConfiguration ?? {};
const synchronizableOptions = (0, _common.grep)(this._getSynchronizableOptionsForCreateComponent(), (value => !(value in configuration)));
const {
integrationOptions: integrationOptions
} = this.option();
let {
nestedComponentOptions: nestedComponentOptions
} = this.option();
nestedComponentOptions = nestedComponentOptions ?? _common.noop;
const nestedComponentConfig = (0, _extend.extend)({
integrationOptions: integrationOptions
}, nestedComponentOptions(this));
synchronizableOptions.forEach((optionName => nestedComponentConfig[optionName] = this.option(optionName)));
this._extendConfig(configuration, nestedComponentConfig);
let instance;
if ((0, _type.isString)(component)) {
const $element = (0, _renderer.default)(element)[component](configuration);
instance = $element[component]("instance")
} else if (element) {
instance = component.getInstance(element);
if (instance) {
instance.option(configuration)
} else {
instance = new component(element, configuration)
}
}
if (instance) {
const optionChangedHandler = _ref => {
let {
name: name,
value: value
} = _ref;
if (synchronizableOptions.includes(name)) {
instance.option(name, value)
}
};
this.on("optionChanged", optionChangedHandler);
instance.on("disposing", (() => this.off("optionChanged", optionChangedHandler)))
}
return instance
}
_extendConfig(configuration, extendConfig) {
(0, _iterator.each)(extendConfig, ((key, value) => {
!Object.prototype.hasOwnProperty.call(configuration, key) && (configuration[key] = value)
}))
}
_defaultActionConfig() {
const $element = this.$element();
const context = this._modelByElement($element);
return (0, _extend.extend)(super._defaultActionConfig(), {
context: context
})
}
_defaultActionArgs() {
const $element = this.$element();
const model = this._modelByElement($element);
const element = this.element();
return (0, _extend.extend)(super._defaultActionArgs(), {
element: element,
model: model
})
}
_optionChanged(args) {
const {
name: name
} = args;
switch (name) {
case "width":
case "height":
this._renderDimensions();
break;
case "rtlEnabled":
this._invalidate();
break;
case "elementAttr":
this._renderElementAttributes();
break;
case "disabled":
case "integrationOptions":
break;
default:
super._optionChanged(args)
}
}
_removeAttributes(element) {
const attrs = element.attributes;
for (let i = attrs.length - 1; i >= 0; i--) {
const attr = attrs[i];
if (attr) {
const {
name: name
} = attr;
if (!name.indexOf("aria-") || -1 !== name.indexOf("dx-") || "role" === name || "style" === name || "tabindex" === name) {
element.removeAttribute(name)
}
}
}
}
_removeClasses(element) {
element.className = element.className.split(" ").filter((cssClass => 0 !== cssClass.lastIndexOf("dx-", 0))).join(" ")
}
_updateDOMComponent(renderRequired) {
if (renderRequired) {
this._renderComponent()
} else if (this._requireRefresh) {
this._requireRefresh = false;
this._refresh()
}
}
endUpdate() {
const renderRequired = this._isInitializingRequired();
super.endUpdate();
this._isUpdateAllowed() && this._updateDOMComponent(renderRequired)
}
$element() {
return this._$element
}
element() {
const $element = this.$element();
return (0, _element.getPublicElement)($element)
}
dispose() {
const element = this.$element().get(0);
(0, _element_data.cleanDataRecursive)(element, true);
element.textContent = "";
this._removeAttributes(element);
this._removeClasses(element)
}
resetOption(optionName) {
super.resetOption(optionName);
if ("width" === optionName || "height" === optionName) {
const initialOption = this.initialOption(optionName);
!(0, _type.isDefined)(initialOption) && this.$element().css(optionName, "")
}
}
_getAnonymousTemplateName() {
return
}
_initTemplateManager() {
if (this._templateManager || !this._useTemplates()) {
return
}
const {
integrationOptions: integrationOptions = {}
} = this.option();
const {
createTemplate: createTemplate
} = integrationOptions;
this._templateManager = new _m_template_manager.default.TemplateManager(createTemplate, this._getAnonymousTemplateName());
this._initTemplates();
return
}
_initTemplates() {
const {
templates: templates,
anonymousTemplateMeta: anonymousTemplateMeta
} = this._templateManager.extractTemplates(this.$element());
const anonymousTemplate = this.option(`integrationOptions.templates.${anonymousTemplateMeta.name}`);
templates.forEach((_ref2 => {
let {
name: name,
template: template
} = _ref2;
this._options.silent(`integrationOptions.templates.${name}`, template)
}));
if (anonymousTemplateMeta.name && !anonymousTemplate) {
this._options.silent(`integrationOptions.templates.${anonymousTemplateMeta.name}`, anonymousTemplateMeta.template);
this._options.silent("_hasAnonymousTemplateContent", true)
}
}
_getTemplateByOption(optionName) {
return this._getTemplate(this.option(optionName))
}
_getTemplate(templateSource) {
const templates = this.option("integrationOptions.templates");
const isAsyncTemplate = this.option("templatesRenderAsynchronously");
const skipTemplates = this.option("integrationOptions.skipTemplates");
return this._templateManager.getTemplate(templateSource, templates, {
isAsyncTemplate: isAsyncTemplate,
skipTemplates: skipTemplates
}, this)
}
_saveTemplate(name, template) {
this._setOptionWithoutOptionChange(`integrationOptions.templates.${name}`, this._templateManager._createTemplate(template))
}
_useTemplates() {
return true
}
}
var _default = exports.default = DOMComponent;