UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

444 lines (380 loc) 12.5 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides control sap.m.Tree. sap.ui.define([ './ListBase', './library', 'sap/ui/model/ClientTreeBindingAdapter', 'sap/ui/model/TreeBindingCompatibilityAdapter', './TreeRenderer', "sap/base/Log", "sap/base/assert", "sap/ui/model/controlhelper/TreeBindingProxy" ], function( ListBase, library, ClientTreeBindingAdapter, TreeBindingCompatibilityAdapter, TreeRenderer, Log, assert, TreeBindingProxy ) { "use strict"; /** * Constructor for a new Tree. * * @param {string} [sId] ID for the new control, generated automatically if no id is given * @param {object} [mSettings] Initial settings for the new control * * @class * The <code>Tree</code> control provides a tree structure for displaying data in a hierarchy. * <b>Note:</b> Growing feature is not supported by <code>Tree</code>. * @extends sap.m.ListBase * * @author SAP SE * @version 1.117.4 * * @constructor * @public * @since 1.42 * @alias sap.m.Tree * @see {@link fiori:/tree/ Tree} */ var Tree = ListBase.extend("sap.m.Tree", { metadata : { library : "sap.m", events : { /** * Fired when an item has been expanded or collapsed by user interaction. * @since 1.50 */ toggleOpenState : { parameters : { /** * Index of the expanded/collapsed item */ itemIndex : {type : "int"}, /** * Binding context of the item */ itemContext : {type : "object"}, /** * Flag that indicates whether the item has been expanded or collapsed */ expanded : {type : "boolean"} } } } }, renderer: TreeRenderer }); Tree.prototype.init = function() { ListBase.prototype.init.apply(this, arguments); this._oProxy = new TreeBindingProxy(this, "items"); }; Tree.prototype.isTreeBinding = function(sName) { return (sName == "items"); }; Tree.prototype.getBinding = function(sName) { // adapt TreeBindingAdapter for Tree sName = sName || "items"; var oBinding = ListBase.prototype.getBinding.call(this, sName); if (oBinding && sName === "items" && !oBinding.getLength) { // try to resolve optional dependencies if (oBinding.isA("sap.ui.model.odata.v2.ODataTreeBinding")) { oBinding.applyAdapterInterface(); } else if (oBinding.isA("sap.ui.model.ClientTreeBinding")) { ClientTreeBindingAdapter.apply(oBinding); } else if (oBinding.isA("sap.ui.model.odata.ODataTreeBinding")) { // use legacy tree binding adapter TreeBindingCompatibilityAdapter(oBinding, this); } else { Log.error("TreeBinding is not supported for the " + this); } } return oBinding; }; Tree.prototype.updateAggregation = function(sName) { if (sName != "items") { return ListBase.prototype.updateAggregation.apply(this, arguments); } // Reuse the ListBinding from ManagedObject.updataAggregation var oBindingInfo = this.getBindingInfo("items"), fnFactory = oBindingInfo.factory, aContexts; // Update a single aggregation with the array of contexts. Reuse existing children // and just append or remove at the end, if some are missing or too many. function update(oControl, aContexts) { var aChildren = oControl.getItems() || [], oContext, oClone; if (aChildren.length > aContexts.length) { for (var i = aContexts.length; i < aChildren.length; i++) { oControl.removeItem(aChildren[i]); aChildren[i].destroy("KeepDom"); } } for (var i = 0; i < aContexts.length; i++) { oContext = aContexts[i]; oClone = aChildren[i]; if (oClone) { oClone.setBindingContext(oContext, oBindingInfo.model); } else { oClone = fnFactory(oControl.getId() + "-" + i, oContext); oClone.setBindingContext(oContext, oBindingInfo.model); oControl.addItem(oClone); } } } // Context length will be filled by model. aContexts = this._oProxy.getContexts(0); // If factory function is used without extended change detection, destroy aggregation if (!oBindingInfo.template) { this.destroyItems(); } update(this, aContexts); }; Tree.prototype.validateAggregation = function(sAggregationName, oObject, bMultiple) { var oResult = ListBase.prototype.validateAggregation.apply(this, arguments); if (sAggregationName === "items" && !oObject.isA("sap.m.TreeItemBase")) { throw new Error(oObject + " is not a valid items aggregation of " + this + ". Items aggregation in Tree control only supports TreeItemBase-based objects, e.g. StandardTreeItem."); } return oResult; }; Tree.prototype.invalidate = function() { ListBase.prototype.invalidate.apply(this, arguments); this._bInvalidated = true; }; Tree.prototype.onAfterRendering = function() { ListBase.prototype.onAfterRendering.apply(this, arguments); this._bInvalidated = false; }; Tree.prototype.exit = function() { ListBase.prototype.exit.apply(this, arguments); this._oProxy = null; }; Tree.prototype._updateDeepestLevel = function(oItem) { // for level change action, e.g. expand if (oItem.getLevel() + 1 > this.getDeepestLevel()) { this._iDeepestLevel = oItem.getLevel() + 1; } }; Tree.prototype.onItemExpanderPressed = function(oItem, bExpand) { var iIndex = this.indexOfItem(oItem); var oBindingInfo = this.getBindingInfo("items"); var oItemContext = oItem && oItem.getBindingContext(oBindingInfo.model); if (oBindingInfo && oItemContext) { var bExpandedBeforePress = oItem.getExpanded(); var bExpandedAfterPress; // make sure when rendering is called, the padding calc uses the correct deepest level this._updateDeepestLevel(oItem); if (bExpand == undefined) { this._oProxy.toggleExpandedState(iIndex); } else if (bExpand) { this._oProxy.expand(iIndex); } else { this._oProxy.collapse(iIndex); } bExpandedAfterPress = this._oProxy.isExpanded(iIndex); if (bExpandedBeforePress !== bExpandedAfterPress && !oItem.isLeaf()) { this.fireToggleOpenState({ itemIndex: iIndex, itemContext: oItemContext, expanded: bExpandedAfterPress }); } } }; /** * The <code>growing</code> property is not supported for control <code>Tree</code>. * @public * @param {boolean} bValue New value for the <code>growing</code> property, ignored. * @returns {this} Returns <code>this</code> to allow method chaining * @deprecated As of version 1.46. */ Tree.prototype.setGrowing = function(bValue) { Log.error("Growing feature of " + this + " is not supported!"); return this; }; /** * The <code>growingThreshold</code> property is not supported for control <code>Tree</code>. * @public * @param {int} iValue New value for the <code>growingThreshold</code> property, ignored. * @returns {this} Returns <code>this</code> to allow method chaining * @deprecated As of version 1.46. */ Tree.prototype.setGrowingThreshold = function(iValue) { Log.error("GrowingThreshold of " + this + " is not supported!"); return this; }; /** * The <code>growingTriggerText</code> property is not supported for control <code>Tree</code>. * @public * @param {string} sValue New value for the <code>growingTriggerText</code> property, ignored. * @returns {this} Returns <code>this</code> to allow method chaining * @deprecated As of version 1.46. */ Tree.prototype.setGrowingTriggerText = function(sValue) { Log.error("GrowingTriggerText of " + this + " is not supported!"); return this; }; /** * The <code>growingScrollToLoad</code> property is not supported for control <code>Tree</code>. * @public * @param {boolean} bValue New value for the <code>growingScrollToLoad</code> property, ignored. * @returns {this} Returns <code>this</code> to allow method chaining * @deprecated As of version 1.46. */ Tree.prototype.setGrowingScrollToLoad = function(bValue) { Log.error("GrowingScrollToLoad of " + this + " is not supported!"); return this; }; /** * The <code>growingDirection</code> property is not supported for control <code>Tree</code>. * @public * @param {sap.m.ListGrowingDirection} sValue New value for the <code>growingDirection</code> property, ignored. * @returns {this} Returns <code>this</code> to allow method chaining * @deprecated As of version 1.46. */ Tree.prototype.setGrowingDirection = function(sValue) { Log.error("GrowingDirection of " + this + " is not supported!"); return this; }; /** * Defines the level to which the tree is expanded. * The function can be used to define the initial expanding state. An alternative way to define the initial expanding state is to set the parameter <code>numberOfExpandedLevels</code> of the binding. * * Example: * <pre> * oTree.bindItems({ * path: "...", * parameters: { * numberOfExpandedLevels: 1 * } * }); * </pre> * @returns {this} Returns <code>this</code> to allow method chaining * @public * @param {int} iLevel The level to which the data is expanded * @since 1.48.0 */ Tree.prototype.expandToLevel = function (iLevel) { this._oProxy.expandToLevel(iLevel); return this; }; Tree.prototype.getNumberOfExpandedLevel = function() { return this.getBinding("items").getNumberOfExpandedLevels(); }; Tree.prototype.getDeepestLevel = function() { if (this._iDeepestLevel === undefined) { this._iDeepestLevel = this.getNumberOfExpandedLevel(); } return this._iDeepestLevel; }; /** * Collapses all nodes. * * @returns {this} A reference to the Tree control * @public * @since 1.48.0 */ Tree.prototype.collapseAll = function () { this._oProxy.collapseAll(); return this; }; Tree.prototype._sortHelper = function (vParam) { var aIndices = []; if ( typeof vParam === "number" ) { aIndices.push(vParam); } else if ( Array.isArray(vParam) ) { //sort aIndices = vParam.sort().reverse(); } return aIndices; }; Tree.prototype._removeLeaf = function(aSortedIndices) { var oItem = null, iItemIndex, aIndices = []; for (var i = 0; i < aSortedIndices.length; i++) { iItemIndex = aSortedIndices[i]; oItem = this.getItems()[iItemIndex]; if (oItem && !oItem.isLeaf()) { aIndices.push(iItemIndex); } } return aIndices; }; Tree.prototype._preExpand = function(vParam) { var aIndices = this._sortHelper(vParam); aIndices = this._removeLeaf(aIndices); return aIndices; }; /** * * Expands one or multiple items. Note that items that are hidden at the time of calling this API can't be expanded. * * @returns {this} A reference to the Tree control * @public * @param {int|int[]} vParam The index or indices of the item to be expanded * @since 1.56.0 */ Tree.prototype.expand = function(vParam) { this._oProxy.expand(vParam); return this; }; /** * * Collapses one or multiple items. * * @returns {this} A reference to the Tree control * @public * @param {int|int[]} vParam The index or indices of the tree items to be collapsed * @since 1.56.0 */ Tree.prototype.collapse = function(vParam) { this._oProxy.collapse(vParam); return this; }; Tree.prototype.getAccessibilityType = function() { return sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("ACC_CTR_TYPE_TREE"); }; Tree.prototype.getAccessbilityPosition = function(oItem) { var iIndex = this.indexOfItem(oItem); return { setSize: this._oProxy.getSiblingCount(iIndex), posInset: this._oProxy.getPositionInParent(iIndex) + 1 }; }; Tree.prototype.onItemLongDragOver = function(oItem) { var iIndex = this.indexOfItem(oItem), oBindingInfo = this.getBindingInfo("items"), oItemContext = oItem && oItem.getBindingContext(oBindingInfo.model); // toggleOpenState event should be fired when an item is expand via DnD interaction if (oItem) { this._updateDeepestLevel(oItem); if (!oItem.isLeaf()) { this._oProxy.expand(iIndex); this.fireToggleOpenState({ itemIndex: iIndex, itemContext: oItemContext, expanded: this._oProxy.isExpanded(iIndex) }); } } }; Tree.prototype.isGrouped = function() { return false; }; Tree.prototype.getAriaRole = function() { return "tree"; }; // items and groupHeader mapping is not required for the table control Tree.prototype.setLastGroupHeader = function() {}; return Tree; });