Ext.namespace('Zarafa.hierarchy.ui'); /** * @class Zarafa.hierarchy.ui.Tree * @extends Ext.tree.TreePanel * @xtype zarafa.hierarchytree * * TreePanel for Hierachy List */ Zarafa.hierarchy.ui.Tree = Ext.extend(Ext.tree.TreePanel, { /** * @cfg {Zarafa.core.ContextModel} model The model which is used to control the * current folder selection from this hierarchy tree. */ model : undefined, /** * @cfg {Zarafa.core.data.HierarchyStore} store store which will be used to get data for hierarchy. */ store : undefined, /** * @cfg {String} IPMFilter The IPM String on which the hierarchy must be filtered */ IPMFilter : undefined, /** * @cfg {Number} permissionFilter The {@link Zarafa.core.mapi.Rights} on which the hierarchy must be filtered */ permissionFilter : undefined, /** * @cfg {Boolean} hideDeletedFolders True to hide the subfolders of "Deleted Items". */ hideDeletedFolders : false, /** * @cfg {Boolean} hideTodoList True to hide the To-do list. */ hideTodoList : false, /** * @cfg {Boolean} hideFavorites True to hide the favorites folder in hierarchy. */ hideFavorites : false, /** * @cfg {Object} config option for {@link Zarafa.hierarchy.ui.FolderNode foldernode} */ nodeConfig : undefined, /** * @cfg {Boolean} deferredLoading True to defer updating the Hierarchy when the panel * is currently not visible. */ deferredLoading : false, /** * The editor which is used for editing a field inside this tree. * @property * @type Zarafa.hierarchy.ui.TreeEditor */ treeEditor : undefined, /** * @cfg {Object} loadMask An {@link Zarafa.common.ui.LoadMask} config or true to mask the {@link Zarafa.hierarchy.ui.Tree Tree} while * loading. Defaults to <code>false</code>. */ loadMask : false, /** * @cfg {Object} treeSorter a {@link Ext.Ext.tree.TreeSorter} config or {@link Boolean} * to sort the {@link Zarafa.hierarchy.ui.Tree Tree} * Defaults to <code>false</code>. */ treeSorter : false, /** * @cfg {Boolean} ddAutoScrollContainer Autodetect a valid container to * {@link Ext.dd.ScrollManager#register register} to the {@link Ext.dd.ScrollManager}. * * When {@link #enableDD} is enabled, but this panel itself does not have any {@link #autoScroll scrollbars}, * enabling this option will allow the class to dynamically detect which parent panel does have scrollbars, * and register that panel to the {@link Ext.dd.ScrollManager}. * Alternatively {@link #ddScrollContainer} can be used to set a certain panel specifically. */ ddAutoScrollContainer : false, /** * @cfg {Ext.Element/Ext.Container} ddScrollContainer A valid container to * {@link Ext.dd.ScrollManager#register register} to the {@link Ext.dd.ScrollManager}. * * When {@link #enableDD} is enabled, but this panel itself does not have any {@link #autoScroll scrollbars}, * setting a component or element to this option will register it to the {@link Ext.dd.ScrollManager}. * Alternatively {@link #ddAutoScrollContainer} can be used to have the container be detected automatically. */ ddScrollContainer : undefined, /** * @cfg {Boolean} defaultOpen Used by {@link #isFolderOpened} to determine if the folder should be opened * by default or not. */ defaultOpen : false, /** * @constructor * @param {Object} config Configuration object */ constructor : function(config) { config = config || {}; if (!config.store) { config.store = container.getHierarchyStore(); } // Configure root node for this component Ext.applyIf(config, { rootVisible : false, autoScroll : true, animate : false, border : false, // The rootnode is the parent node under which all Stores will be visualized, // because it is not part of the actual hierarchy but more of a helper node, // this node is invisible by default. root : new Zarafa.hierarchy.ui.HierarchyRootNode() }); Zarafa.hierarchy.ui.Tree.superclass.constructor.call(this, config); // sort tree if(this.treeSorter && !(this.treeSorter instanceof Ext.tree.TreeSorter)) { this.treeSorter = new Zarafa.hierarchy.ui.TreeSorter(this, Ext.apply({}, this.treeSorter)); } }, /** * Function will initialize {@link Zarafa.hierarchy.ui.Tree Tree} and creates a * {@link Zarafa.common.ui.LoadMask} if {@link Zarafa.hierarchy.ui.Tree Tree} is intantiated as full tree. * @protected */ initComponent : function() { // Intialize the loader if (!this.loader) { this.loader = new Zarafa.hierarchy.data.HierarchyTreeLoader({ tree : this, store : this.store, nodeConfig : this.nodeConfig, deferredLoading : this.deferredLoading }); } // call parent Zarafa.hierarchy.ui.Tree.superclass.initComponent.apply(this, arguments); // When DD is enabled within container scrolling, we must register a hook // to determine the container on which we are going to scroll. if (this.enableDD === true) { if (this.ddAutoScrollContainer === true) { this.on('load', this.autodetectScrollContainer, this); } else if (this.ddScrollContainer) { this.ddScrollContainer = Ext.Element(this.ddScrollContainer) ? this.ddScrollContainer : this.ddScrollContainer.el; this.registerScrollContainer(this.ddScrollContainer); } } // create load mask if(this.loadMask) { this.on('render', this.createLoadMask, this); } }, /** * When {@link #ddAutoScrollContainer} has been enabled, this function will walk * up the parents of the current component parent which is scrollable. The {@link Ext.Container#body} * will then be used for {@link #registerScrollContainer}. * @private */ autodetectScrollContainer : function() { var ct = this.ownerCt; while (ct && ct.autoScroll !== true) { ct = ct.ownerCt; } if (ct) { // When autoScroll is enabled, the 'body' of the component will // have the the actuall scrollbar attached to it. this.registerScrollContainer(ct.body || ct.el); } }, /** * Register the given {@link Ext.Element} with the * {@link Ext.dd.ScrollManager ScrollManager}. * @param {Ext.Element} el The element to register to the scrollmanager * @private */ registerScrollContainer : function(el) { // Apply some extra configuration options // which are used by the ScrollManager. el.ddScrollConfig = { vthresh: 50, hthresh: -1, frequency: 100, increment: 25 }; Ext.dd.ScrollManager.register(el); }, /** * Function will create {@link Zarafa.common.ui.LoadMask} which will be shown * when loading the {@link Zarafa.hierarchy.ui.Tree Tree}. * @private */ createLoadMask : function() { this.loadMask = new Zarafa.common.ui.LoadMask(this.getEl(), Ext.apply({store: this.store}, this.loadMask)); }, /** * @return True when this tree has an {@link #IPMFilter} applied */ hasFilter : function() { return !Ext.isEmpty(this.IPMFilter); }, /** * The filter which is applied for filtering nodes from the * {@link Zarafa.hierarchy.ui.Tree HierarchyTree}. * @param {Object} folder the folder to filter * @return {Boolean} true to accept the folder */ nodeFilter : function(folder) { var hide = false; // Check if the folder matches the requested IPMFilter if (Ext.isDefined(this.IPMFilter)) { hide = !folder.isContainerClass(this.IPMFilter, false); } // Check if the folder matches the requested permissionFilter if (!hide && Ext.isDefined(this.permissionFilter)) { hide = !(folder.get('rights') & this.permissionFilter); } // Check if the folder is located in Deleted items if (!hide && this.hideDeletedFolders) { hide = folder.isInDeletedItems(); } // Check if the to-do list should be shown if (!hide && this.hideTodoList) { hide = folder.isTodoListFolder(); } // Check if the favorites list folder should be shown if (!hide && this.hideFavorites) { hide = folder.isFavoritesRootFolder(); } return !hide; }, /** * @return {Array} list of all childnodes * @private */ getAllNodes : function() { return this.getRootNode().childNodes; }, /** * Manual selection of the treeNode to which the folder is attached in the tree. * This will first ensure the given folder {@link #ensureFolderVisible is visible} * and will then {@link Ext.tree.DefaultSelectionModel#select select the given node} in the tree. * @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder The folder to select * @param {Boolean} ensureVisibility True to make given folder visible in screen moving scroll bar. * @return {Boolean} True when the TreeNode for the given folder existed, and could be selected. */ selectFolderInTree : function(folder, ensureVisibility) { var treeNode; if (ensureVisibility !== false) { treeNode = this.ensureFolderVisible(folder); } else { treeNode = this.getTreeNode(folder); } if (treeNode) { this.getSelectionModel().select(treeNode, undefined, ensureVisibility); return true; } else { return false; } }, /** * This will call {@link Ext.tree.TreeNode#ensureVisible} in the node * to which the given folder is attached. This will first make sure * that the actual folder has been loaded by the parent folder. * @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder The folder which must * be made visible. * @return {Zarafa.hierarchy.ui.FolderNode} The node which was made visible, * false if the folder was not found in the hierarchy. */ ensureFolderVisible : function(folder) { var treeNode = this.getTreeNode(folder); // If the tree has not been found, take the parent folder. if (!treeNode) { var parentfolder = folder.getParentFolder(); if (!parentfolder) { return false; } // With the parent folder we can ensure that folder is visible, // and expand it to ensure the subfolders will be rendered. var parentNode = this.ensureFolderVisible(parentfolder); if (!parentNode) { return false; } parentNode.expand(); // With luck, the node has now been created. treeNode = this.getTreeNode(folder); } if (treeNode) { // Ensure that the given node is visible. // WARNING: After this call, treeNode is destroyed // as the TreeLoader will have reloaded the parent! treeNode.ensureVisible(); // Obtain the new treeNode reference, update the UI and return it. treeNode = this.getTreeNode(folder); treeNode.update(true); return treeNode; } return false; }, /** * Check if the folder should be opened by default or not. * @param {Zarafa.hierarchy.data.MAPIFolderRecord} folder The folder to check * @return {Boolean} True if the folder should be expanded by default * @private */ isFolderOpened : function(folder) { return folder.isIPMSubTree() || folder.isFavoritesRootFolder() || this.defaultOpen; }, /** * Call {@link Zarafa.hierarchy.ui.FolderNode}#{@link Zarafa.hierarchy.ui.FolderNode#update update} * on {@link #getAllNodes all nodes}. * @protected */ updateAll : function() { var nodes = this.getAllNodes(); for (var i = 0; i < nodes.length; i++) { nodes[i].update(true); } }, /** * Function will destroy load mask and calls parent class' beforeDestroy. * @private */ beforeDestroy : function() { if (this.rendered && this.loadMask) { Ext.destroy(this.loadMask); this.loadMask = false; } if (this.treeSorter) { Ext.destroy(this.treeSorter); this.treeSorter = false; } Zarafa.hierarchy.ui.Tree.superclass.beforeDestroy.call(this); }, /** * Function is used to find the {@link Zarafa.hierarchy.ui.FolderNode} based on the folder. * If selected folder is {@link Zarafa.common.favorites.data.FavoritesFolderRecord favorites} folder then * we append "favorites-" keyword with folder entryid to uniquely identify and get the favorites marked folder node. * * @param {Zarafa.hierarchy.data.MAPIFolderRecord | Zarafa.common.favorites.data.FavoritesFolderRecord} folder the folder * can be favorites folder or any noramal folder. * @returns {Zarafa.hierarchy.ui.FolderNode} folder node object */ getTreeNode: function (folder) { var id = folder.get('entryid'); if (folder.isFavoritesFolder()) { id = "favorites-"+id; } return this.getNodeById(id); } }); Ext.reg('zarafa.hierarchytree', Zarafa.hierarchy.ui.Tree);