UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

640 lines (632 loc) • 24.7 kB
/** * DevExtreme (cjs/__internal/viz/core/m_base_widget.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 _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine")); var _devices = _interopRequireDefault(require("../../../core/devices")); var _dom_adapter = _interopRequireDefault(require("../../../core/dom_adapter")); var _dom_component = _interopRequireDefault(require("../../../core/dom_component")); var _renderer = _interopRequireDefault(require("../../../core/renderer")); var _common = require("../../../core/utils/common"); var _deferred = require("../../../core/utils/deferred"); var _extend = require("../../../core/utils/extend"); var _iterator = require("../../../core/utils/iterator"); var _size = require("../../../core/utils/size"); var _type = require("../../../core/utils/type"); var _window = require("../../../core/utils/window"); var _base_theme_manager = require("../../../viz/core/base_theme_manager"); var _base_widget = require("../../../viz/core/base_widget.utils"); var _errors_warnings = _interopRequireDefault(require("../../../viz/core/errors_warnings")); var _helpers = require("../../../viz/core/helpers"); var _layout = _interopRequireDefault(require("../../../viz/core/layout")); var _renderer2 = require("../../../viz/core/renderers/renderer"); var _utils = require("../../../viz/core/utils"); var _utils2 = require("../../../viz/utils"); var _m_charts = _interopRequireDefault(require("../../common/m_charts")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const { log: log } = _errors_warnings.default; const OPTION_RTL_ENABLED = "rtlEnabled"; const SIZED_ELEMENT_CLASS = "dx-sized-element"; const baseOptionMethod = _dom_component.default.prototype.option; function getTrue() { return true } function getFalse() { return false } function defaultOnIncidentOccurred(e) { if (!e.component._eventsStrategy.hasEvent("incidentOccurred")) { log.apply(null, [e.target.id].concat(e.target.args || [])) } } function pickPositiveValue(values) { return values.reduce(((result, value) => value > 0 && !result ? value : result), 0) } const getEmptyComponent = function() { const emptyComponentConfig = { _initTemplates() {}, ctor(element, options) { this.callBase(element, options); const sizedElement = _dom_adapter.default.createElement("div"); const width = options && (0, _type.isNumeric)(options.width) ? `${options.width}px` : "100%"; const height = options && (0, _type.isNumeric)(options.height) ? `${options.height}px` : `${this._getDefaultSize().height}px`; _dom_adapter.default.setStyle(sizedElement, "width", width); _dom_adapter.default.setStyle(sizedElement, "height", height); _dom_adapter.default.setClass(sizedElement, "dx-sized-element", false); _dom_adapter.default.insertElement(element, sizedElement) } }; const EmptyComponent = _dom_component.default.inherit(emptyComponentConfig); const originalInherit = EmptyComponent.inherit; EmptyComponent.inherit = function(config) { Object.keys(config).forEach((field => { if ((0, _type.isFunction)(config[field]) && "_" !== field.substr(0, 1) && "option" !== field || "_dispose" === field || "_optionChanged" === field) { config[field] = _common.noop } })); return originalInherit.call(this, config) }; return EmptyComponent }; function callForEach(functions) { functions.forEach((c => c())) } const isServerSide = !(0, _window.hasWindow)(); function sizeIsValid(value) { return (0, _type.isDefined)(value) && value > 0 } const baseWidget = isServerSide ? getEmptyComponent() : _dom_component.default.inherit({ _eventsMap: { onIncidentOccurred: { name: "incidentOccurred", actionSettings: { excludeValidators: ["disabled"] } }, onDrawn: { name: "drawn", actionSettings: { excludeValidators: ["disabled"] } } }, _getDefaultOptions() { return (0, _extend.extend)(this.callBase(), { onIncidentOccurred: defaultOnIncidentOccurred }) }, _useLinks: true, _init() { this._$element.children(".dx-sized-element").remove(); this._graphicObjects = {}; this.callBase(...arguments); this._changesLocker = 0; this._optionChangedLocker = 0; this._asyncFirstDrawing = true; this._changes = (0, _helpers.changes)(); this._suspendChanges(); this._themeManager = this._createThemeManager(); this._themeManager.setCallback((() => { this._requestChange(this._themeDependentChanges) })); this._renderElementAttributes(); this._initRenderer(); const useLinks = this._useLinks; if (useLinks) { this._renderer.root.enableLinks().virtualLink("core").virtualLink("peripheral") } this._renderVisibilityChange(); this._attachVisibilityChangeHandlers(); this._toggleParentsScrollSubscription(this._isVisible()); this._initEventTrigger(); this._incidentOccurred = (0, _base_widget.createIncidentOccurred)(this.NAME, this._eventTrigger); this._layout = new _layout.default; if (useLinks) { this._renderer.root.linkAfter("core") } this._initPlugins(); this._initCore(); if (useLinks) { this._renderer.root.linkAfter() } this._change(this._initialChanges) }, _createThemeManager() { return new _base_theme_manager.BaseThemeManager(this._getThemeManagerOptions()) }, _getThemeManagerOptions() { return { themeSection: this._themeSection, fontFields: this._fontFields } }, _initialChanges: ["LAYOUT", "RESIZE_HANDLER", "THEME", "DISABLED"], _initPlugins() { (0, _iterator.each)(this._plugins, ((_, plugin) => { plugin.init.call(this) })) }, _disposePlugins() { (0, _iterator.each)(this._plugins.slice().reverse(), ((_, plugin) => { plugin.dispose.call(this) })) }, _change(codes) { this._changes.add(codes) }, _suspendChanges() { this._changesLocker += 1 }, _resumeChanges() { if (0 === --this._changesLocker && this._changes.count() > 0 && !this._applyingChanges) { this._renderer.lock(); this._applyingChanges = true; this._applyChanges(); this._changes.reset(); this._applyingChanges = false; this._changesApplied(); this._renderer.unlock(); if (this._optionsQueue) { this._applyQueuedOptions() } this.resolveItemsDeferred(this._legend ? [this._legend] : []); this._optionChangedLocker += 1; this._notify(); this._optionChangedLocker -= 1 } }, resolveItemsDeferred(items) { this._resolveDeferred(this._getTemplatesItems(items)) }, _collectTemplatesFromItems: items => items.reduce(((prev, i) => ({ items: prev.items.concat(i.getTemplatesDef()), groups: prev.groups.concat(i.getTemplatesGroups()) })), { items: [], groups: [] }), _getTemplatesItems(items) { const elements = this._collectTemplatesFromItems(items); const extraItems = this._getExtraTemplatesItems(); return { items: extraItems.items.concat(elements.items), groups: extraItems.groups.concat(elements.groups), launchRequest: [extraItems.launchRequest], doneRequest: [extraItems.doneRequest] } }, _getExtraTemplatesItems: () => ({ items: [], groups: [], launchRequest: () => {}, doneRequest: () => {} }), _resolveDeferred(_ref) { let { items: items, launchRequest: launchRequest, doneRequest: doneRequest, groups: groups } = _ref; this._setGroupsVisibility(groups, "hidden"); if (this._changesApplying) { this._changesApplying = false; callForEach(doneRequest); return } let syncRendering = true; _deferred.when.apply(this, items).done((() => { var _groups$; const isGroupInDom = !(null !== (_groups$ = groups[0]) && void 0 !== _groups$ && _groups$.element) || !!(0, _renderer.default)(groups[0].element.closest("svg")).length; if (!isGroupInDom) { return } if (syncRendering) { this._setGroupsVisibility(groups, "visible"); return } callForEach(launchRequest); this._changesApplying = true; const changes = ["LAYOUT", "FULL_RENDER"]; if (this._asyncFirstDrawing) { changes.push("FORCE_FIRST_DRAWING"); this._asyncFirstDrawing = false } else { changes.push("FORCE_DRAWING") } this._requestChange(changes); this._setGroupsVisibility(groups, "visible") })); syncRendering = false }, _setGroupsVisibility(groups, visibility) { groups.forEach((g => g.attr({ visibility: visibility }))) }, _applyQueuedOptions() { const queue = this._optionsQueue; this._optionsQueue = null; this.beginUpdate(); (0, _iterator.each)(queue, ((_, action) => { action() })); this.endUpdate() }, _requestChange(codes) { this._suspendChanges(); this._change(codes); this._resumeChanges() }, _applyChanges() { const changes = this._changes; const order = this._totalChangesOrder; const changesOrderLength = order.length; for (let i = 0; i < changesOrderLength; i += 1) { if (changes.has(order[i])) { this[`_change_${order[i]}`]() } } }, _optionChangesOrder: ["EVENTS", "THEME", "RENDERER", "RESIZE_HANDLER"], _layoutChangesOrder: ["ELEMENT_ATTR", "CONTAINER_SIZE", "LAYOUT"], _customChangesOrder: ["DISABLED"], _change_EVENTS() { this._eventTrigger.applyChanges() }, _change_THEME() { this._setThemeAndRtl() }, _change_RENDERER() { this._setRendererOptions() }, _change_RESIZE_HANDLER() { this._setupResizeHandler() }, _change_ELEMENT_ATTR() { this._renderElementAttributes(); this._change(["CONTAINER_SIZE"]) }, _change_CONTAINER_SIZE() { this._updateSize() }, _change_LAYOUT() { this._setContentSize() }, _change_DISABLED() { const renderer = this._renderer; const { root: root } = renderer; if (this.option("disabled")) { this._initDisabledState = root.attr("pointer-events"); root.attr({ "pointer-events": "none", filter: renderer.getGrayScaleFilter().id }) } else if ("none" === root.attr("pointer-events")) { root.attr({ "pointer-events": (0, _type.isDefined)(this._initDisabledState) ? this._initDisabledState : null, filter: null }) } }, _themeDependentChanges: ["RENDERER"], _initRenderer() { const rawCanvas = this._calculateRawCanvas(); this._canvas = (0, _utils2.floorCanvasDimensions)(rawCanvas); this._renderer = new _renderer2.Renderer({ cssClass: `${this._rootClassPrefix} ${this._rootClass}`, pathModified: this.option("pathModified"), container: this._$element[0] }); this._renderer.resize(this._canvas.width, this._canvas.height) }, _disposeRenderer() { this._renderer.dispose() }, _disposeGraphicObjects() { Object.keys(this._graphicObjects).forEach((id => { this._graphicObjects[id].dispose() })); this._graphicObjects = null }, _getAnimationOptions: _common.noop, render() { this._requestChange(["CONTAINER_SIZE"]); const visible = this._isVisible(); this._toggleParentsScrollSubscription(visible); !visible && this._stopCurrentHandling() }, _toggleParentsScrollSubscription(subscribe) { let $parents = (0, _renderer.default)(this._renderer.root.element).parents(); if ("generic" === _devices.default.real().platform) { $parents = $parents.add((0, _window.getWindow)()) } this._proxiedTargetParentsScrollHandler = this._proxiedTargetParentsScrollHandler || function() { this._stopCurrentHandling() }.bind(this); _events_engine.default.off((0, _renderer.default)("").add(this._$prevRootParents), "scroll.viz_widgets", this._proxiedTargetParentsScrollHandler); if (subscribe) { _events_engine.default.on($parents, "scroll.viz_widgets", this._proxiedTargetParentsScrollHandler); this._$prevRootParents = $parents } }, _stopCurrentHandling: _common.noop, _dispose() { if (this._disposed) { return } this.callBase(...arguments); this._toggleParentsScrollSubscription(false); this._removeResizeHandler(); this._layout.dispose(); this._eventTrigger.dispose(); this._disposeCore(); this._disposePlugins(); this._disposeGraphicObjects(); this._disposeRenderer(); this._themeManager.dispose(); this._themeManager = null; this._renderer = null; this._eventTrigger = null }, _initEventTrigger() { this._eventTrigger = (0, _base_widget.createEventTrigger)(this._eventsMap, ((name, actionSettings) => this._createActionByOption(name, actionSettings))) }, _calculateRawCanvas() { const size = this.option("size") || {}; const margin = this.option("margin") || {}; const defaultCanvas = this._getDefaultSize() || {}; const getSizeOfSide = (size, side, getter) => { if (sizeIsValid(size[side]) || !(0, _window.hasWindow)()) { return 0 } const elementSize = getter(this._$element); return elementSize <= 1 ? 0 : elementSize }; const elementWidth = getSizeOfSide(size, "width", (x => (0, _size.getWidth)(x))); const elementHeight = getSizeOfSide(size, "height", (x => (0, _size.getHeight)(x))); let canvas = { width: size.width <= 0 ? 0 : pickPositiveValue([size.width, elementWidth, defaultCanvas.width]), height: size.height <= 0 ? 0 : pickPositiveValue([size.height, elementHeight, defaultCanvas.height]), left: pickPositiveValue([margin.left, defaultCanvas.left]), top: pickPositiveValue([margin.top, defaultCanvas.top]), right: pickPositiveValue([margin.right, defaultCanvas.right]), bottom: pickPositiveValue([margin.bottom, defaultCanvas.bottom]) }; if (canvas.width - canvas.left - canvas.right <= 0 || canvas.height - canvas.top - canvas.bottom <= 0) { canvas = { width: 0, height: 0 } } return canvas }, _updateSize() { const rawCanvas = this._calculateRawCanvas(); if ((0, _utils2.areCanvasesDifferent)(this._canvas, rawCanvas) || this.__forceRender) { this._canvas = (0, _utils2.floorCanvasDimensions)(rawCanvas); this._recreateSizeDependentObjects(true); this._renderer.resize(this._canvas.width, this._canvas.height); this._change(["LAYOUT"]) } }, _recreateSizeDependentObjects: _common.noop, _getMinSize: () => [0, 0], _getAlignmentRect: _common.noop, _setContentSize() { const canvas = this._canvas; const layout = this._layout; let rect = canvas.width > 0 && canvas.height > 0 ? [canvas.left, canvas.top, canvas.width - canvas.right, canvas.height - canvas.bottom] : [0, 0, 0, 0]; rect = layout.forward(rect, this._getMinSize()); const nextRect = this._applySize(rect) || rect; layout.backward(nextRect, this._getAlignmentRect() || nextRect) }, _getOption(name, isScalar) { const theme = this._themeManager.theme(name); const option = this.option(name); return isScalar ? void 0 !== option ? option : theme : (0, _extend.extend)(true, {}, theme, option) }, _setupResizeHandler() { const redrawOnResize = (0, _utils.parseScalar)(this._getOption("redrawOnResize", true), true); if (this._disposeResizeHandler) { this._removeResizeHandler() } this._disposeResizeHandler = (0, _base_widget.createResizeHandler)(this._$element[0], redrawOnResize, (() => this._requestChange(["CONTAINER_SIZE"]))) }, _removeResizeHandler() { if (this._disposeResizeHandler) { this._disposeResizeHandler(); this._disposeResizeHandler = null } }, _onBeginUpdate: _common.noop, beginUpdate() { if (this._initialized && this._isUpdateAllowed()) { this._onBeginUpdate(); this._suspendChanges() } this.callBase(...arguments); return this }, endUpdate() { this.callBase(); this._isUpdateAllowed() && this._resumeChanges(); return this }, option(name) { if (this._initialized && this._applyingChanges && (arguments.length > 1 || (0, _type.isObject)(name))) { this._optionsQueue = this._optionsQueue || []; this._optionsQueue.push(this._getActionForUpdating(arguments)) } else { return baseOptionMethod.apply(this, arguments) } }, _getActionForUpdating(args) { return () => { baseOptionMethod.apply(this, args) } }, _clean: _common.noop, _render: _common.noop, _optionChanged(arg) { if (this._optionChangedLocker) { return } const partialChanges = this.getPartialChangeOptionsName(arg); let changes = []; if (partialChanges.length > 0) { partialChanges.forEach((pc => changes.push(this._partialOptionChangesMap[pc]))) } else { changes.push(this._optionChangesMap[arg.name]) } changes = changes.filter((c => !!c)); if (this._eventTrigger.change(arg.name)) { this._change(["EVENTS"]) } else if (changes.length > 0) { this._change(changes) } else { this.callBase.apply(this, arguments) } }, _notify: _common.noop, _changesApplied: _common.noop, _optionChangesMap: { size: "CONTAINER_SIZE", margin: "CONTAINER_SIZE", redrawOnResize: "RESIZE_HANDLER", theme: "THEME", rtlEnabled: "THEME", encodeHtml: "THEME", elementAttr: "ELEMENT_ATTR", disabled: "DISABLED" }, _partialOptionChangesMap: {}, _partialOptionChangesPath: {}, getPartialChangeOptionsName(changedOption) { const { fullName: fullName } = changedOption; const sections = fullName.split(/[.]/); const { name: name } = changedOption; const { value: value } = changedOption; const options = this._partialOptionChangesPath[name]; const partialChangeOptionsName = []; if (options) { if (true === options) { partialChangeOptionsName.push(name) } else { options.forEach((op => { fullName.indexOf(op) >= 0 && partialChangeOptionsName.push(op) })); if (1 === sections.length) { if ("object" === (0, _type.type)(value)) { this._addOptionsNameForPartialUpdate(value, options, partialChangeOptionsName) } else if ("array" === (0, _type.type)(value)) { if (value.length > 0 && value.every((item => this._checkOptionsForPartialUpdate(item, options)))) { value.forEach((item => { this._addOptionsNameForPartialUpdate(item, options, partialChangeOptionsName) })) } } } } } return partialChangeOptionsName.filter(((value, index, self) => self.indexOf(value) === index)) }, _checkOptionsForPartialUpdate: (optionObject, options) => !Object.keys(optionObject).some((key => -1 === options.indexOf(key))), _addOptionsNameForPartialUpdate(optionObject, options, partialChangeOptionsName) { const optionKeys = Object.keys(optionObject); if (this._checkOptionsForPartialUpdate(optionObject, options)) { optionKeys.forEach((key => options.indexOf(key) > -1 && partialChangeOptionsName.push(key))) } }, _visibilityChanged() { this.render() }, _setThemeAndRtl() { this._themeManager.setTheme(this.option("theme"), this.option("rtlEnabled")) }, _getRendererOptions() { return { rtl: this.option("rtlEnabled"), encodeHtml: this.option("encodeHtml"), animation: this._getAnimationOptions() } }, _setRendererOptions() { this._renderer.setOptions(this._getRendererOptions()) }, svg() { return this._renderer.svg() }, getSize() { const canvas = this._canvas || {}; return { width: canvas.width, height: canvas.height } }, isReady: getFalse, _dataIsReady: getTrue, _resetIsReady() { this.isReady = getFalse }, _renderGraphicObjects() { const renderer = this._renderer; const graphics = _m_charts.default.getGraphicObjects(); Object.keys(graphics).forEach((id => { if (!this._graphicObjects[id]) { const { type: type, colors: colors, rotationAngle: rotationAngle, template: template, width: width, height: height } = graphics[id]; switch (type) { case "linear": this._graphicObjects[id] = renderer.linearGradient(colors, id, rotationAngle); break; case "radial": this._graphicObjects[id] = renderer.radialGradient(colors, id); break; case "pattern": this._graphicObjects[id] = renderer.customPattern(id, this._getTemplate(template), width, height) } } })) }, _drawn() { this.isReady = getFalse; if (this._dataIsReady()) { this._renderer.onEndAnimation((() => { this.isReady = getTrue })) } this._eventTrigger("drawn", {}) } }); var _default = exports.default = baseWidget; (0, _helpers.replaceInherit)(baseWidget);