/** * DevExtreme (ui/responsive_box.js) * Version: 19.1.16 * Build date: Tue Oct 18 2022 * * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var $ = require("../core/renderer"); var eventsEngine = require("../events/core/events_engine"); var commonUtils = require("../core/utils/common"); var typeUtils = require("../core/utils/type"); var errors = require("./widget/ui.errors"); var windowUtils = require("../core/utils/window"); var window = windowUtils.getWindow(); var iteratorUtils = require("../core/utils/iterator"); var extend = require("../core/utils/extend").extend; var registerComponent = require("../core/component_registrator"); var Box = require("./box"); var CollectionWidget = require("./collection/ui.collection_widget.edit"); var RESPONSIVE_BOX_CLASS = "dx-responsivebox"; var SCREEN_SIZE_CLASS_PREFIX = RESPONSIVE_BOX_CLASS + "-screen-"; var BOX_ITEM_CLASS = "dx-box-item"; var BOX_ITEM_DATA_KEY = "dxBoxItemData"; var HD_SCREEN_WIDTH = 1920; var ResponsiveBox = CollectionWidget.inherit({ _getDefaultOptions: function() { return extend(this.callBase(), { rows: [], cols: [], screenByWidth: null, singleColumnScreen: "", height: "100%", width: "100%", activeStateEnabled: false, focusStateEnabled: false, onItemStateChanged: void 0, onLayoutChanged: null, currentScreenFactor: void 0, _layoutStrategy: void 0 }) }, _init: function() { if (!this.option("screenByWidth")) { this._options.screenByWidth = windowUtils.defaultScreenFactorFunc } this.callBase(); this._initLayoutChangedAction() }, _initLayoutChangedAction: function() { this._layoutChangedAction = this._createActionByOption("onLayoutChanged", { excludeValidators: ["disabled", "readonly"] }) }, _itemClass: function() { return BOX_ITEM_CLASS }, _itemDataKey: function() { return BOX_ITEM_DATA_KEY }, _initMarkup: function() { this.callBase(); this.$element().addClass(RESPONSIVE_BOX_CLASS); this._updateRootBox() }, _updateRootBox: function() { clearTimeout(this._updateTimer); this._updateTimer = setTimeout(function() { if (this._$root) { eventsEngine.triggerHandler(this._$root, "dxupdate") } }.bind(this)) }, _renderItems: function() { this._setScreenSize(); this._screenItems = this._itemsByScreen(); this._prepareGrid(); this._spreadItems(); this._layoutItems(); this._linkNodeToItem() }, _itemOptionChanged: function(item) { var $item = this._findItemElementByItem(item); if (!$item.length) { return } this._refreshItem($item, item); this._clearItemNodeTemplates(); this._update() }, _setScreenSize: function() { var currentScreen = this._getCurrentScreen(); this._removeScreenSizeClass(); this.$element().addClass(SCREEN_SIZE_CLASS_PREFIX + currentScreen); this.option("currentScreenFactor", currentScreen) }, _removeScreenSizeClass: function() { var currentScreenFactor = this.option("currentScreenFactor"); currentScreenFactor && this.$element().removeClass(SCREEN_SIZE_CLASS_PREFIX + currentScreenFactor) }, _prepareGrid: function() { var grid = this._grid = []; this._prepareRowsAndCols(); iteratorUtils.each(this._rows, function() { var row = []; grid.push(row); iteratorUtils.each(this._cols, function() { row.push(this._createEmptyCell()) }.bind(this)) }.bind(this)) }, getSingleColumnRows: function() { var rows = this.option("rows"); var screenItemsLength = this._screenItems.length; if (rows.length) { var filteredRows = this._filterByScreen(rows); var result = []; for (var i = 0; i < screenItemsLength; i++) { var sizeConfig = this._defaultSizeConfig(); if (i < filteredRows.length && typeUtils.isDefined(filteredRows[i].shrink)) { sizeConfig.shrink = filteredRows[i].shrink } result.push(sizeConfig) } return result } else { return this._defaultSizeConfig(screenItemsLength) } }, _prepareRowsAndCols: function() { if (this._isSingleColumnScreen()) { this._prepareSingleColumnScreenItems(); this._rows = this.getSingleColumnRows(); this._cols = this._defaultSizeConfig(1) } else { this._rows = this._sizesByScreen(this.option("rows")); this._cols = this._sizesByScreen(this.option("cols")) } }, _isSingleColumnScreen: function() { return this._screenRegExp().test(this.option("singleColumnScreen")) || !this.option("rows").length || !this.option("cols").length }, _prepareSingleColumnScreenItems: function() { this._screenItems.sort(function(item1, item2) { return item1.location.row - item2.location.row || item1.location.col - item2.location.col }); iteratorUtils.each(this._screenItems, function(index, item) { extend(item.location, { row: index, col: 0, rowspan: 1, colspan: 1 }) }) }, _sizesByScreen: function(sizeConfigs) { return iteratorUtils.map(this._filterByScreen(sizeConfigs), function(sizeConfig) { return extend(this._defaultSizeConfig(), sizeConfig) }.bind(this)) }, _createDefaultSizeConfig: function() { return { ratio: 1, baseSize: 0, minSize: 0, maxSize: 0 } }, _defaultSizeConfig: function(size) { var defaultSizeConfig = this._createDefaultSizeConfig(); if (!arguments.length) { return defaultSizeConfig } var result = []; for (var i = 0; i < size; i++) { result.push(defaultSizeConfig) } return result }, _filterByScreen: function(items) { var screenRegExp = this._screenRegExp(); return commonUtils.grep(items, function(item) { return !item.screen || screenRegExp.test(item.screen) }) }, _screenRegExp: function() { var screen = this._getCurrentScreen(); return new RegExp("(^|\\s)" + screen + "($|\\s)", "i") }, _getCurrentScreen: function() { var width = this._screenWidth(); return this.option("screenByWidth")(width) }, _screenWidth: function() { return windowUtils.hasWindow() ? $(window).width() : HD_SCREEN_WIDTH }, _createEmptyCell: function() { return { item: {}, location: { colspan: 1, rowspan: 1 } } }, _spreadItems: function() { iteratorUtils.each(this._screenItems, function(_, itemInfo) { var location = itemInfo.location || {}; var itemCol = location.col; var itemRow = location.row; var row = this._grid[itemRow]; var itemCell = row && row[itemCol]; this._occupyCells(itemCell, itemInfo) }.bind(this)) }, _itemsByScreen: function() { var _this = this; return this.option("items").reduce(function(result, item) { var locations = item.location || {}; locations = typeUtils.isPlainObject(locations) ? [locations] : locations; _this._filterByScreen(locations).forEach(function(location) { result.push({ item: item, location: extend({ rowspan: 1, colspan: 1 }, location) }) }); return result }, []) }, _occupyCells: function(itemCell, itemInfo) { if (!itemCell || this._isItemCellOccupied(itemCell, itemInfo)) { return } extend(itemCell, itemInfo); this._markSpanningCell(itemCell) }, _isItemCellOccupied: function(itemCell, itemInfo) { if (!typeUtils.isEmptyObject(itemCell.item)) { return true } var result = false; this._loopOverSpanning(itemInfo.location, function(cell) { result = result || !typeUtils.isEmptyObject(cell.item) }); return result }, _loopOverSpanning: function(location, callback) { var rowEnd = location.row + location.rowspan - 1; var colEnd = location.col + location.colspan - 1; var boundRowEnd = Math.min(rowEnd, this._rows.length - 1); var boundColEnd = Math.min(colEnd, this._cols.length - 1); location.rowspan -= rowEnd - boundRowEnd; location.colspan -= colEnd - boundColEnd; for (var rowIndex = location.row; rowIndex <= boundRowEnd; rowIndex++) { for (var colIndex = location.col; colIndex <= boundColEnd; colIndex++) { if (rowIndex !== location.row || colIndex !== location.col) { callback(this._grid[rowIndex][colIndex]) } } } }, _markSpanningCell: function(itemCell) { this._loopOverSpanning(itemCell.location, function(cell) { extend(cell, { item: itemCell.item, spanningCell: itemCell }) }) }, _linkNodeToItem: function() { iteratorUtils.each(this._itemElements(), function(_, itemNode) { var $item = $(itemNode); var item = $item.data(BOX_ITEM_DATA_KEY); if (!item.box) { item.node = $item.children() } }) }, _layoutItems: function() { var rowsCount = this._grid.length; var colsCount = rowsCount && this._grid[0].length; if (!rowsCount && !colsCount) { return } var result = this._layoutBlock({ direction: "col", row: { start: 0, end: rowsCount - 1 }, col: { start: 0, end: colsCount - 1 } }); var rootBox = this._prepareBoxConfig(result.box || { direction: "row", items: [extend(result, { ratio: 1 })] }); extend(rootBox, this._rootBoxConfig(rootBox.items)); this._$root = $("