UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

384 lines (329 loc) 14.6 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ /** * Contains functionality that is used in sap.m.IconTabBar Drag&Drop */ sap.ui.define([ 'sap/ui/core/dnd/DragInfo', 'sap/ui/core/dnd/DropInfo', "sap/ui/events/KeyCodes", 'sap/ui/core/library', 'sap/ui/core/Configuration' ], function(DragInfo, DropInfo, KeyCodes, coreLibrary, Configuration) { "use strict"; // shortcut for sap.ui.core.dnd.DropPosition var DropPosition = coreLibrary.dnd.DropPosition; var INSERT_POSITION_BEFORE = "Before", INSERT_BEFORE = "insertBefore", INSERT_AFTER = "insertAfter", sInsertAfterBeforePosition, DRAG_DROP_GROUP_NAME = "IconTabReorder", DRAG_DIRECTION_FORWARD = "Forward", DRAG_DIRECTION_BACKWARD = "Backward"; var IconTabBarDragAndDropUtil = { /** * Inserts control at correct place in the DOM. * @param {string} sInsertAfterBeforePosition comes from drop event, it can be "Before" or "After" * @param {object} oDraggedControl control that is being dragged * @param {object} oDroppedControl control that the dragged control will be dropped on * @param {boolean} bIsOverflow */ _insertControl: function(sInsertAfterBeforePosition, oDraggedControl, oDroppedControl, bIsOverflow) { var $DraggedControl = oDraggedControl.$(), $DroppedControl = oDroppedControl.$(), aDraggedControlSubItems = [], aDroppedControlSubItems = []; if (oDraggedControl._getNestedLevel() > 1 && oDroppedControl._getNestedLevel() > 1) { aDraggedControlSubItems = oDraggedControl._getRootTab()._getSelectList().getItems().filter(function (oItem) { return oDraggedControl._getRealTab()._isParentOf(oItem._getRealTab()); }); aDroppedControlSubItems = oDroppedControl._getRootTab()._getSelectList().getItems().filter(function (oItem) { return oDroppedControl._getRealTab()._isParentOf(oItem._getRealTab()); }); } if (bIsOverflow) { var aOverflowSelectListItems = oDraggedControl._getRootTab().getParent()._getOverflow()._getSelectList().getItems(); aDraggedControlSubItems = aOverflowSelectListItems.filter(function (oItem) { return oDraggedControl._getRealTab()._isParentOf(oItem._getRealTab()); }); aDroppedControlSubItems = aOverflowSelectListItems.filter(function (oItem) { return oDroppedControl._getRealTab()._isParentOf(oItem._getRealTab()); }); } if (sInsertAfterBeforePosition === INSERT_AFTER) { $DraggedControl.insertAfter($DroppedControl); } else { $DraggedControl.insertBefore($DroppedControl); } aDraggedControlSubItems.reverse().forEach(function (oChildItem) { oChildItem.$().insertAfter($DraggedControl); }); aDroppedControlSubItems.reverse().forEach(function (oChildItem) { oChildItem.$().insertAfter($DroppedControl); }); }, /** * Handles drop event. * @param {object} oContext from which context function is called (sap.m.IconTabHeader or sap.m.IconTabSelectList) * @param {string} sDropPosition comes from drop event, it can be "Before", "After", or "On" * @param {object} oDraggedControl control that is being dragged * @param {object} oDroppedControl control that the dragged control will be dropped on * @param {boolean} bIgnoreRTL should RTL configuration be ignored for drag and drop logic * @param {number} allowedNestingLevels allowed number of nesting tabs via drag and drop */ handleDrop: function (oContext, sDropPosition, oDraggedControl, oDroppedControl, bIgnoreRTL, allowedNestingLevels) { var iBeginDragIndex = oContext.indexOfItem(oDraggedControl), iDropIndex = oContext.indexOfItem(oDroppedControl), iAggregationDropIndex = 0, bRtl = Configuration.getRTL(), bIsDropPositionBefore = sDropPosition === INSERT_POSITION_BEFORE, //_getNestedLevel returns 1 there is no nesting currentNestedLevel = oDroppedControl._getNestedLevel() - 1; // Prevent cycle if (oDraggedControl._isParentOf(oDroppedControl)) { return; } if (currentNestedLevel === allowedNestingLevels && sDropPosition === DropPosition.On) { return; } if (bRtl && !bIgnoreRTL) { if (bIsDropPositionBefore) { iAggregationDropIndex = iBeginDragIndex < iDropIndex ? iDropIndex : iDropIndex + 1; sInsertAfterBeforePosition = INSERT_AFTER; } else { iAggregationDropIndex = iBeginDragIndex < iDropIndex ? iDropIndex - 1 : iDropIndex; sInsertAfterBeforePosition = INSERT_BEFORE; } } else { if (bIsDropPositionBefore) { iAggregationDropIndex = iBeginDragIndex < iDropIndex ? iDropIndex - 1 : iDropIndex; sInsertAfterBeforePosition = INSERT_BEFORE; } else { iAggregationDropIndex = iBeginDragIndex < iDropIndex ? iDropIndex : iDropIndex + 1; sInsertAfterBeforePosition = INSERT_AFTER; } } if (oContext.isA("sap.m.IconTabFilter") || !oDraggedControl.getParent().isA("sap.m.IconTabHeader")){ if (bIsDropPositionBefore) { iAggregationDropIndex = iDropIndex; } else { iAggregationDropIndex = iDropIndex + 1; } } IconTabBarDragAndDropUtil._insertControl(sInsertAfterBeforePosition, oDraggedControl, oDroppedControl); if (sDropPosition === DropPosition.On) { if (oDroppedControl === oDraggedControl) { return; } iAggregationDropIndex = oContext.getAggregation("items").length; } IconTabBarDragAndDropUtil._handleConfigurationAfterDragAndDrop.call(oContext, oDraggedControl, iAggregationDropIndex); }, /** * Recalculates and sets the correct aria-posinset attribute value. * @private */ _updateAccessibilityInfo: function () { var oIconTabHeaderItems = this.getItems(), iAriaPointSet = 1, oItemDom; oIconTabHeaderItems.forEach(function (oItem) { oItemDom = oItem.getDomRef(); if (oItemDom && oItemDom.getAttribute("aria-posinset") !== null) { oItemDom.setAttribute("aria-posinset", iAriaPointSet++); } }); }, /** * Handles aggregation of control after drag and drop. * @param {object} oDraggedControl Dragged control * @param {number} iDropIndex Drop index * @private */ _handleConfigurationAfterDragAndDrop: function (oDraggedControl, iDropIndex) { var aDraggedControlSubItems = [], oIconTabHeader = this.isA("sap.m.IconTabHeader") ? this : this._getIconTabHeader(); if (this.isA("sap.m.IconTabBarSelectList")) { aDraggedControlSubItems = this.getItems().filter(function (oItem) { return oDraggedControl._getRealTab()._isParentOf(oItem._getRealTab()); }); } oIconTabHeader._setPreserveSelection(true); this.removeAggregation('items', oDraggedControl, true); this.insertAggregation('items', oDraggedControl, iDropIndex, true); aDraggedControlSubItems.forEach(function (oItem) { this.removeAggregation('items', oItem, true); }.bind(this)); var iNewDragIndex = 1 + this.indexOfAggregation('items', oDraggedControl); aDraggedControlSubItems.reverse().forEach(function (oItem) { this.insertAggregation('items', oItem, iNewDragIndex, true); }.bind(this)); oIconTabHeader._setPreserveSelection(false); IconTabBarDragAndDropUtil._updateAccessibilityInfo.call(this); }, /** * Decreases the drop index. * @param {int} iBeginDragIndex Index of dragged control * @param {sap.m.IconTabFilter[]} aItems All items in the header/select list * @returns {int} The new index of the item * @private */ _decreaseDropIndex: function (iBeginDragIndex, aItems) { var iPrevIndex = iBeginDragIndex - 1; // Jump over invisible items and sub items while (iPrevIndex >= 0 && (aItems[iBeginDragIndex]._getRealTab()._getNestedLevel() !== aItems[iPrevIndex]._getRealTab()._getNestedLevel() || !aItems[iPrevIndex].getVisible() || (!aItems[iBeginDragIndex].$().hasClass("sapMITBFilterHidden") && aItems[iPrevIndex].$().hasClass("sapMITBFilterHidden")))) { iPrevIndex--; } if (iPrevIndex < 0) { sInsertAfterBeforePosition = INSERT_AFTER; return iBeginDragIndex; } sInsertAfterBeforePosition = INSERT_BEFORE; return iPrevIndex; }, /** * Increases the drop index. * @param {int} iBeginDragIndex Index of dragged control * @param {array} aItems All items in the header * @param {int} iMaxIndex Maximum allowed index. For the header this is the end of the tab strip. * @returns {int} The new index of the item * @private */ _increaseDropIndex: function (iBeginDragIndex, aItems, iMaxIndex) { var iNextIndex = iBeginDragIndex + 1; // Jump over invisible items and sub items while (iNextIndex < aItems.length && (aItems[iBeginDragIndex]._getRealTab()._getNestedLevel() !== aItems[iNextIndex]._getRealTab()._getNestedLevel() || !aItems[iNextIndex].getVisible())) { iNextIndex++; } if (iNextIndex > iMaxIndex) { sInsertAfterBeforePosition = INSERT_BEFORE; return iBeginDragIndex; } sInsertAfterBeforePosition = INSERT_AFTER; return iNextIndex; }, /** * Moves focused control depending on the combinations of pressed keys. * * @param {object} oDraggedControl Control that is going to be moved * @param {number} iKeyCode Key code * @param {int} iMaxIndex Maximum allowed index. For the header this is the end of the tab strip. * @returns {boolean} returns true is scrolling will be needed */ moveItem: function (oDraggedControl, iKeyCode, iMaxIndex) { var aItems = this.getItems(), iBeginDragIndex = this.indexOfItem(oDraggedControl), bRtl = Configuration.getRTL(), iNewDropIndex, bPrevent; if (this.isA("sap.m.IconTabFilter")){ aItems = this._getRealTab().getItems(); } switch (iKeyCode) { //Handles Ctrl + Home case KeyCodes.HOME: iNewDropIndex = 0; sInsertAfterBeforePosition = INSERT_BEFORE; break; //Handles Ctrl + End case KeyCodes.END: iNewDropIndex = aItems.length - 1; sInsertAfterBeforePosition = INSERT_AFTER; break; // Handles Ctrl + Left Arrow case KeyCodes.ARROW_LEFT: if (bRtl) { bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_FORWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._increaseDropIndex(iBeginDragIndex, aItems, iMaxIndex); } else { bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_BACKWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._decreaseDropIndex(iBeginDragIndex, aItems); } break; // Handles Ctrl + Right Arrow case KeyCodes.ARROW_RIGHT: if (bRtl) { bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_BACKWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._decreaseDropIndex(iBeginDragIndex, aItems); } else { bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_FORWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._increaseDropIndex(iBeginDragIndex, aItems, iMaxIndex); } break; // Handles Ctrl + Arrow Down case KeyCodes.ARROW_DOWN: bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_FORWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._increaseDropIndex(iBeginDragIndex, aItems, iMaxIndex); break; // Handles Ctrl + Arrow Up case KeyCodes.ARROW_UP: bPrevent = IconTabBarDragAndDropUtil.preventDragBetweenSubItems(oDraggedControl, DRAG_DIRECTION_BACKWARD, this); iNewDropIndex = IconTabBarDragAndDropUtil._decreaseDropIndex(iBeginDragIndex, aItems); break; default: return false; } if (bPrevent) { return false; } if (!this.isA("sap.m.IconTabFilter")) { var oDroppedControl = aItems[iNewDropIndex]; IconTabBarDragAndDropUtil._insertControl(sInsertAfterBeforePosition, oDraggedControl, oDroppedControl, this._oTabFilter && this._oTabFilter._bIsOverflow); } IconTabBarDragAndDropUtil._handleConfigurationAfterDragAndDrop.call(this, oDraggedControl, iNewDropIndex); return true; }, /** * Adding aggregations for drag and drop. * @param {object} context from which context function is called (sap.m.IconTabHeader or sap.m.IconTabSelectList) * @param {string} sDropLayout Depending on the control we are dragging in, it could be Vertical or Horizontal * @param {object} oDropPosition Depending on maxNestingLevel, value could be 'On' or 'Between' */ setDragDropAggregations: function (context, sDropLayout, oDropPosition) { var oIconTabHeader = context._oIconTabHeader ? context._oIconTabHeader : context; var sIconTabHeaderId = oIconTabHeader.getId(); //Adding Drag&Drop configuration to the dragDropConfig aggregation if needed context.addDragDropConfig(new DragInfo({ sourceAggregation: "items", groupName: DRAG_DROP_GROUP_NAME + sIconTabHeaderId })); context.addDragDropConfig(new DropInfo({ targetAggregation: "items", dropPosition: oDropPosition, dropLayout: sDropLayout, drop: context._handleDragAndDrop.bind(context), groupName: DRAG_DROP_GROUP_NAME + sIconTabHeaderId })); }, /** * Prevents drag and drop to be executed between different level sub items in sap.m.IconTabBarSelectList. * @param {object} oDraggedControl Control that is going to be moved * @param {string} sDirection Depending on the direction of we are dragging in, it could be Forward or Backward * @param {object} oContext from which context function is called (sap.m.IconTabHeader or sap.m.IconTabSelectList) * * @returns {boolean} returns true is scrolling will be needed */ preventDragBetweenSubItems: function (oDraggedControl, sDirection, oContext) { var bPrevent = false; if (oContext.isA("sap.m.IconTabBarSelectList")) { var oRealTab = oDraggedControl._getRealTab(), oParent = oRealTab.getParent(), aChildren = oParent.getItems(); if ((aChildren.indexOf(oRealTab) === 0 && sDirection === DRAG_DIRECTION_BACKWARD) || (aChildren.indexOf(oRealTab) + 1 === aChildren.length && sDirection === DRAG_DIRECTION_FORWARD) || aChildren.length === 1) { bPrevent = true; } } return bPrevent; } }; return IconTabBarDragAndDropUtil; });