'use strict'; /** * Licensed Materials - Property of IBM * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2013, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['../../../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../LayoutHelper', 'jquery', 'underscore', './feature/CommonAuthoringFeature'], function (Base, LayoutHelper, $, _, CommonAuthoringFeature) { var BaseLayout = null; BaseLayout = Base.extend({ init: function init(options) { BaseLayout.inherited('init', this, arguments); this.consumeView = options.consumeView; // the consume view this.overridden = {}; // container for functions overridden in consume view this.added = []; //track all 'new' added functions in consume view //{setup helpers ... initialize from consume view this.domNode = this.consumeView.domNode; this.id = this.consumeView.id; this.layoutController = this.consumeView.layoutController; this.model = this.consumeView.model; this.getNodeId = this.consumeView.getNodeId.bind(this.consumeView); //}setup helpers //override functions in consume view this.specializeConsumeView(['add', 'removeChild', 'onResize', 'onResizeStep', 'getWidgetPositionUpdate', 'getMinimumTop', 'getMinimumLeft', 'getMaximumHeight', 'getMaximumWidth', 'getPhysicalPageSize', 'onShow']); this.consumeView.authorHelper = this; this.consumeView.isAuthoringMode = true; this.commonAuthoringFeature = new CommonAuthoringFeature(this.consumeView); this.dashboardApi = options.dashboardApi; this.$el = $(this.domNode); }, specializeConsumeView: function specializeConsumeView(funcNames) { _.each(funcNames, function (funcName) { if (this.consumeView[funcName] && this.added.indexOf(funcName) === -1) { if (!this.overridden[funcName]) { //save original if we have not already this.overridden[funcName] = this.consumeView[funcName].bind(this.consumeView); } } else { this.added.push(funcName); } //add specialized func this.consumeView[funcName] = this[funcName].bind(this); }.bind(this)); }, restoreSpecializedFunc: function restoreSpecializedFunc(funcName) { if (this.overridden[funcName]) { this.consumeView[funcName] = this.overridden[funcName]; } }, restoreAllSpecialized: function restoreAllSpecialized() { for (var name in this.overridden) { if (this.overridden.hasOwnProperty(name)) { this.restoreSpecializedFunc(name); } } }, removeAllAddedFuncs: function removeAllAddedFuncs() { for (var i = 0; i < this.added.length; i++) { if (this.consumeView[this.added[i]]) { this.consumeView[this.added[i]] = null; } } }, renderContent: function renderContent() { return this.overridden.renderContent(); }, onResize: function onResize(renderOptions) { this.overridden.onResize(renderOptions); }, onShow: function onShow() { this.overridden.onShow(arguments); }, /** * Called when a resize starts and continuously called for each resize step * */ onResizeStep: function onResizeStep() { this.commonAuthoringFeature.onResizeStep(); }, destroy: function destroy() { BaseLayout.inherited('destroy', this, arguments); this.restoreAllSpecialized(); this.removeAllAddedFuncs(); this.commonAuthoringFeature.destroy(); this.consumeView.isAuthoringMode = false; }, /** * Add a node to the view * @param layoutView * @param insertBeforeId */ add: function add(layoutView, insertBeforeId) { this.consumeView._subLayoutViews.push(layoutView); var node = layoutView.domNode; if (!node) { return; } if (node.parentNode) { node.parentNode.removeChild(node); } var insertBeforeNode = insertBeforeId ? $('#' + this.getNodeId(insertBeforeId), this.layoutController.$el)[0] : null; this.domNode.insertBefore(node, insertBeforeNode); }, /** * Remove a layout from the view * @param node * */ removeChild: function removeChild(layoutView) { this.consumeView._subLayoutViews = this.consumeView._subLayoutViews.filter(function (view) { return view !== layoutView; }); // Simply detach and not remove(). We might be moving the layout to a different parent. if (layoutView && layoutView.domNode) { $(layoutView.domNode).detach(); } }, /** * Return the model update object that represent the state of the given node info */ getWidgetPositionUpdate: function getWidgetPositionUpdate(nodeInfo) { var update = null; if (nodeInfo.node._layout) { var siblingId = nodeInfo.dropPosition.before && nodeInfo.dropPosition.before._layout ? nodeInfo.dropPosition.before._layout.model.id : null; var xPosition = nodeInfo.dropPosition.x; var yPosition = nodeInfo.dropPosition.y; var $node = $(nodeInfo.node); var width = xPosition + $node.width(); var maxWidth = this.getMaximumWidth(); if (maxWidth && width > maxWidth) { xPosition = maxWidth - $node.width(); } var height = yPosition + $node.height(); var maxHeight = this.getMaximumHeight(); if (maxHeight && height > maxHeight) { yPosition = maxHeight - $node.height(); } update = { style: { left: Math.max(this.getMinimumLeft(), xPosition) + 'px', top: Math.max(this.getMinimumTop(), yPosition) + 'px' }, insertBefore: siblingId, parentId: this.model.id, id: nodeInfo.node._layout.model.id }; if (nodeInfo.dropPosition.height) { update.style.height = nodeInfo.dropPosition.height + 'px'; } if (nodeInfo.dropPosition.width) { update.style.width = nodeInfo.dropPosition.width + 'px'; } } return update; }, getMaximumWidth: function getMaximumWidth() { var pageSize = this.getPhysicalPageSize(); if (pageSize) { return pageSize.width; } else { return Infinity; } }, getMaximumHeight: function getMaximumHeight() { var pageSize = this.getPhysicalPageSize(); if (pageSize) { return pageSize.height; } else { return Infinity; } }, getMinimumTop: function getMinimumTop() { var paddingTop = parseInt(this.$el.css('padding-top'), 10); return isNaN(paddingTop) ? 0 : paddingTop; }, getMinimumLeft: function getMinimumLeft() { var paddingLeft = parseInt(this.$el.css('padding-left'), 10); return isNaN(paddingLeft) ? 0 : paddingLeft; }, //general helper _addWidget: function _addWidget(widgetSpec, isTouch) { var _this = this; var transactionApi = this.dashboardApi.getFeature('Transaction'); var transactionToken = transactionApi.startTransaction(); var widgetModel = widgetSpec.model; var content = { containerId: widgetSpec.parentId, type: 'widget.' + widgetModel.type, spec: widgetModel, properties: widgetSpec.layoutProperties.style }; return this.dashboardApi.getCanvas().addContent(content, transactionToken).then(function (contentApi) { transactionApi.endTransaction(transactionToken); return _this.layoutController.whenWidgetRenderComplete(contentApi.getId()).done(function (layout) { var selectionHandler = _this.layoutController.interactionController.selectionHandler; selectionHandler.deselectAll(); // pass the flag isTouch to properly render the resize edges for touch device. selectionHandler.selectNode(layout.domNode, { 'isTouch': isTouch }); }); }); }, _getModelToAddFromDragObject: function _getModelToAddFromDragObject(dragObject) { var canvasDnD = this.dashboardApi.getFeature('CanvasDnD'); return canvasDnD.onDrop(dragObject); }, _processWidgetSpecForPin: function _processWidgetSpecForPin(widgetSpec, isTouch) { if (widgetSpec.contentType === 'boardFragment') { var fragmentModel = { layout: widgetSpec.content.layout, widgets: widgetSpec.content.widgets, dataSources: widgetSpec.content.dataSources, properties: widgetSpec.content.properties, sourceName: widgetSpec.sourceName }; if (widgetSpec.content.drillThrough) { fragmentModel.drillThrough = widgetSpec.content.drillThrough; } if (widgetSpec.content.episodes) { fragmentModel.episodes = widgetSpec.content.episodes; } var options = { model: fragmentModel, parentId: widgetSpec.parentId }; var payload = this.model.boardModel.addFragment(options, 'layoutBaseView_onPinDrop', null); // The newly added widget from pin needs to be selected after finishing rendering if (payload && payload.value && payload.value.parameter && payload.value.parameter.model.layout && payload.value.parameter.model.layout.id) { this.layoutController.whenWidgetRenderComplete(payload.value.parameter.model.layout.id).done(function (layout) { var selectionHandler = this.layoutController.interactionController.selectionHandler; selectionHandler.deselectAll(); // pass the flag isTouch to properly render the resize edges for touch device. selectionHandler.selectNode(layout.domNode, { 'isTouch': isTouch }); }.bind(this)); } } else { this._addWidget(widgetSpec, isTouch); } this.dashboardApi.getFeature('Colors').clearLocalPaletteCache(); }, /** * Returns the displayable page size for the view (in pixels) */ getPhysicalPageSize: function getPhysicalPageSize(layoutPositioning, id) { var layoutPos = layoutPositioning || this.model.getLayoutPositioning(true); if (layoutPos === 'absolute') { // The display page size in absolute is the configured page size return this.model.boardModel.layout.get('pageSize'); } else if (layoutPos === 'relative') { // The display page size is just a ratio in relative, calculate the page size return this._getRelativePhysicalPageSize(id); } else { return { width: this.domNode.offsetWidth, height: this.domNode.offsetHeight }; } }, _getRelativePhysicalPageSize: function _getRelativePhysicalPageSize(id) { var $firstVisiblePage = void 0, pageSize = {}; if (this.$el.is(':visible')) { // Use the page if it is visible pageSize = { width: this.$el.width(), height: this.$el.height() }; } else { // Page is not visible if (id) { $firstVisiblePage = $(LayoutHelper.getLayoutContentContainer(this.layoutController.topLayoutModel.id, id, this.dashboardApi)); } else { $firstVisiblePage = $(this.layoutController.getLayoutContentContainer()); } if ($firstVisiblePage.length) { var firstVisiblePageLayoutPos = $firstVisiblePage[0]._layout.model.getLayoutPositioning(true); if (firstVisiblePageLayoutPos === 'relative') { // If the first visible page is the same type as this page, then use its page size pageSize = { width: $firstVisiblePage.width(), height: $firstVisiblePage.height() }; } else { // The dashboard has not be upgraded to the new layout (mixed layouts on tabs) // Current page layout is relative and first visible page is absolute // Calculate current relative pageSize using relative ratio on visible absolute page size var $absoluteContainer = $firstVisiblePage.parent(); var currentPageSize = this.model.boardModel.layout.get('pageSize'); pageSize = { width: $absoluteContainer.width(), height: $absoluteContainer.width() * (currentPageSize.height / currentPageSize.width) }; } } else { // No visible pages to base the page size off, we shouldn't be here return { width: this.domNode.offsetWidth, height: this.domNode.offsetHeight }; } } return pageSize; }, /**This function with reposition a widget if it is outside the bounds of the dashboard * @param maxHeight - maximum height of the layout specified in style * @param maxWidth - maximum width of the layout specified in style * @param style - expected to have height and width properties to compare with maxHeight and maxWidth. Will be resized to fit. */ moveToFitBoundaries: function moveToFitBoundaries(maxHeight, maxWidth, style) { // widgets placed outside of layout will be bumped in if (style.top + style.height > maxHeight) { style.top = maxHeight - style.height; } if (style.left + style.width > maxWidth) { style.left = maxWidth - style.width; } }, /** * Update the model for this view * @public * @function LayoutBaseView#updateModel * @param {Object[]} styleUpdateArray Styles to be updated * @param {TransactionToken} transactionToken transactionToken * @param {boolean} [validate = true] Flag the indicating whether to validate the styles */ updateModel: function updateModel(styleUpdateArray, transactionToken) { var _this2 = this; var validate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; styleUpdateArray.forEach(function (styleUpdate) { var content = _this2.dashboardApi.getCanvas().getContent(styleUpdate.id); var options = Object.assign({}, transactionToken, { validatePropertyValue: false }); Object.keys(styleUpdate.style).forEach(function (propertyName) { content.setPropertyValue(propertyName, styleUpdate.style[propertyName], options); }); //we have to do this twice so we know the properties are all set before validating. options.validatePropertyValue = validate; Object.keys(styleUpdate.style).forEach(function (propertyName) { content.setPropertyValue(propertyName, styleUpdate.style[propertyName], options); }); }); } }); return BaseLayout; }); //# sourceMappingURL=LayoutBaseView.js.map