@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
248 lines (228 loc) • 10.7 kB
JavaScript
/* eslint-disable max-nested-callbacks */
/*!
* OpenUI5
* (c) Copyright 2009-2023 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
sap.ui.define(["sap/base/Log"], function(Log) {
"use strict";
/**
* Change handler for moving table columns.
*
* @alias sap.m.changeHandler.MoveTableColumns
* @author SAP SE
* @version 1.117.4
* @experimental Since 1.48
*/
var MoveTableColumns = {};
var SOURCE_ALIAS = "source";
var TARGET_ALIAS = "target";
var MOVED_ELEMENTS_ALIAS = "movedElements";
var COLUMNS_AGGREGATION_NAME = "columns";
var CELLS_AGGREGATION_NAME = "cells";
var ITEMS_AGGREGATION_NAME = "items";
function fnSwitchCells(oModifier, oView, oRow, iSourceIndex, iTargetIndex) {
return Promise.resolve()
.then(oModifier.getAggregation.bind(oModifier, oRow, CELLS_AGGREGATION_NAME))
.then(function(aCells) {
// ColumnListItem and GroupHeaderListItem are only allowed for the tables items aggregation.
if (!aCells) {
Log.warning("Aggregation cells to move not found");
return Promise.reject();
}
if (iSourceIndex < 0 || iSourceIndex >= aCells.length) {
Log.warning("Move cells in table item called with invalid index: " + iSourceIndex);
return Promise.reject();
}
var oMovedCell = aCells[iSourceIndex];
return Promise.resolve()
.then(oModifier.removeAggregation.bind(oModifier,oRow, CELLS_AGGREGATION_NAME, oMovedCell))
.then(oModifier.insertAggregation.bind(oModifier, oRow, CELLS_AGGREGATION_NAME, oMovedCell, iTargetIndex, oView));
});
}
function fnMoveColumns(oModifier, oView, oTable, iSourceIndex, iTargetIndex) {
return Promise.resolve()
.then(oModifier.getAggregation.bind(oModifier, oTable, ITEMS_AGGREGATION_NAME))
.then(function(aItems) {
return aItems.reduce(function(oPreviousPromise, oItem) {
return oPreviousPromise
.then(function() {
if (oModifier.getControlType(oItem) !== "sap.m.GroupHeaderListItem") {
return fnSwitchCells(oModifier, oView, oItem, iSourceIndex, iTargetIndex);
}
return undefined;
});
}, Promise.resolve());
});
}
/**
* Moves a column from one index to another.
* @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control
* @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move
* @param {object} mPropertyBag Map of properties
* @param {object} mPropertyBag.view XML node representing a ui5 view
* @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls
* @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent
* @param {function} fnIterator - Iterator function which is called on each movedElement, as an argument it gets CurrentIndex
* of the element and may return TargetIndex as a result.
* @return {Promise} Promise resolving when change was applied
*/
function _applyChange(oChange, oRelevantContainer, mPropertyBag, fnIterator) {
var oModifier = mPropertyBag.modifier;
var oView = mPropertyBag.view;
var oAppComponent = mPropertyBag.appComponent;
var oChangeContent = oChange.getContent();
var oTargetSource = oChange.getDependentControl(SOURCE_ALIAS, mPropertyBag);
var oTable = oChange.getDependentControl(TARGET_ALIAS, mPropertyBag);
var aColumns;
var oMovedElement;
return Promise.resolve()
.then(function() {
return oModifier.getAggregation(oTable, COLUMNS_AGGREGATION_NAME);
})
.then(function(aRetrievedColumns){
aColumns = aRetrievedColumns;
if (oTargetSource !== oTable) {
Log.warning("Moving columns between different tables is not yet supported.");
return Promise.reject(false);
}
// Fetch the information about the movedElements together with the source and target index.
return oChangeContent.movedElements.reduce(function (oPreviousPromise, mMovedElement) {
var iSourceIndex;
var iTargetIndex;
var iCurrentIndexInAggregation;
var iStoredSourceIndexInChange;
var sMovedElementId;
return oPreviousPromise.then(function() {
oMovedElement = oModifier.bySelector(mMovedElement.selector, oAppComponent, oView);
if (!oMovedElement) {
sMovedElementId = mMovedElement.selector && mMovedElement.selector.id;
Log.warning("The table column with id: '" + sMovedElementId + "' stored in the change is not found and the move operation cannot be applied");
return Promise.reject();
}
iCurrentIndexInAggregation = aColumns.indexOf(oMovedElement);
iStoredSourceIndexInChange = mMovedElement.sourceIndex;
iTargetIndex = typeof fnIterator === "function" && fnIterator(iStoredSourceIndexInChange);
iTargetIndex = typeof iTargetIndex === "number" ? iTargetIndex : mMovedElement.targetIndex;
if (iCurrentIndexInAggregation !== iTargetIndex) {
// By default we are getting the index from the aggregation, because it is possible that the order is
// already modified and the column that we want to move is not on the passed source index
iSourceIndex = iCurrentIndexInAggregation;
} else {
// In RTA edit mode, the condition will be false, because the aggregation is modified by the drag and drop action.
// Therefore, we need to use the passed source index
iSourceIndex = iStoredSourceIndexInChange;
}
// move children in `columns` aggregation
return oModifier.removeAggregation(oTable, COLUMNS_AGGREGATION_NAME, oMovedElement);
})
.then(function(){
return oModifier.insertAggregation(oTable, COLUMNS_AGGREGATION_NAME, oMovedElement, iTargetIndex, oView);
})
// move children in `items` aggregation (actual content)
.then(function() {
return oModifier.getBindingTemplate(oTable, ITEMS_AGGREGATION_NAME);
})
.then(function(oTemplate) {
if (oTemplate) {
return fnSwitchCells(oModifier, oView, oTemplate, iSourceIndex, iTargetIndex)
.then(oModifier.updateAggregation.bind(oModifier, oTable, ITEMS_AGGREGATION_NAME));
} else {
return fnMoveColumns(oModifier, oView, oTable, iSourceIndex, iTargetIndex);
}
});
}, Promise.resolve());
});
}
/**
* Moves a column from one index to another.
*
* @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control
* @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move
* @param {object} mPropertyBag Map of properties
* @param {object} mPropertyBag.view XML node representing a ui5 view
* @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls
* @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent
* @return {Promise} Promise resolving when change was applied
* @public
*/
MoveTableColumns.applyChange = function (oChange, oRelevantContainer, mPropertyBag) {
var aRevertData = [];
return Promise.resolve()
.then(function(){
return _applyChange(oChange, oRelevantContainer, mPropertyBag, function (iStoredSourceIndexInChange) {
aRevertData.unshift({
index: iStoredSourceIndexInChange
});
});
})
.then(function() {
oChange.setRevertData(aRevertData);
});
};
/**
* Reverts the change
*
* @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control
* @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move
* @param {object} mPropertyBag Map of properties
* @param {object} mPropertyBag.view XML node representing a ui5 view
* @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls
* @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent
* @return {Promise} Promise resolving when change was reverted
* @public
*/
MoveTableColumns.revertChange = function (oChange, oRelevantContainer, mPropertyBag) {
var aRevertData = oChange.getRevertData();
return Promise.resolve()
.then(function(){
return _applyChange(oChange, oRelevantContainer, mPropertyBag, function () {
var mItem = aRevertData.shift();
return mItem && mItem.index;
});
})
.then(function() {
oChange.resetRevertData();
});
};
/**
* Completes the change by adding change handler specific content.
*
* @param {sap.ui.fl.Change} oChange Change object to be completed
* @param {object} mSpecificChangeInfo Determines the attributes <code>source</code>, <code>target</code> and <code>movedElements</code> which are included in the change
* @param {object} mPropertyBag Map of properties
* @param {sap.ui.core.UiComponent} mPropertyBag.appComponent Component in which the change should be applied
* @public
*/
MoveTableColumns.completeChangeContent = function (oChange, mSpecificChangeInfo, mPropertyBag) {
var oModifier = mPropertyBag.modifier;
var oAppComponent = mPropertyBag.appComponent;
var oSourceControl = oModifier.bySelector(mSpecificChangeInfo.source.id, oAppComponent);
var oTargetControl = oModifier.bySelector(mSpecificChangeInfo.target.id, oAppComponent);
var mAdditionalSourceInfo = {
aggregation: mSpecificChangeInfo.source.aggregation,
type: oModifier.getControlType(oSourceControl)
};
var mAdditionalTargetInfo = {
aggregation: mSpecificChangeInfo.target.aggregation,
type: oModifier.getControlType(oTargetControl)
};
// We need to add the information about the movedElements together with the source and target index
var oContent = {movedElements: []};
mSpecificChangeInfo.movedElements.forEach(function (mElement) {
var oElement = mElement.element || oModifier.bySelector(mElement.id, oAppComponent);
oContent.movedElements.push({
selector: oModifier.getSelector(oElement, oAppComponent),
sourceIndex: mElement.sourceIndex,
targetIndex: mElement.targetIndex
});
});
oChange.setContent(oContent);
oChange.addDependentControl(mSpecificChangeInfo.source.id, SOURCE_ALIAS, mPropertyBag, mAdditionalSourceInfo);
oChange.addDependentControl(mSpecificChangeInfo.target.id, TARGET_ALIAS, mPropertyBag, mAdditionalTargetInfo);
oChange.addDependentControl(mSpecificChangeInfo.movedElements.map(function (element) {
return element.id;
}), MOVED_ELEMENTS_ALIAS, mPropertyBag);
};
return MoveTableColumns;
}, /* bExport= */ true);