/* Copyright (c) 2006-2007, ePages GmbH All Rights Reserved. epages.cartridges.de_epages.presentation.widget.Objectcontroller $Revision: 1.46 $ */ dojo.provide("epages.cartridges.de_epages.presentation.widget.Objecttree"); dojo.require("dijit.Tree"); dojo.require("epages.event"); dojo.declare( "epages.cartridges.de_epages.presentation.widget.Objecttree", [dijit.Tree], { /** * public properties */ selectedNodeId : undefined, persist : false, /** * private properties */ _translation : new epages.io.Translation(dojo.moduleUrl('epages.cartridges.de_epages.presentation.widget', 'templates/translation'), 'auto'), // epages.io.Translation - translation object postCreate : function() { this.inherited("postCreate", arguments); dojo.subscribe(this.model.store.id+'/changePosition',this,'_onStoreChangePosition'); dojo.subscribe(this.model.store.id+'/changeParent',this,'_onStoreChangeParent'); dojo.subscribe(this.model.store.id+'/changeVisibility',this,'_onStoreChangeVisibility'); dojo.subscribe(this.model.store.id+'/reloadStore',this,'_reloadTree'); var me = this; //set Children state when node expands dojo.subscribe(this.id+'/nodeexpand',function(node){ me.setChildrenState(node); }); // add item for root object this.item = this.model.store.fetchItemByIdentity(this.model.query.id); dojo.mixin(this.rootNode.item,this.item); // set Selected node on load if(this.selectedNodeId){ this.focusNodeById(this.selectedNodeId); } //set Icons for Children of Tree and connect setChildren method to prototype of TreeNodes this.setChildrenState(this.rootNode); // set Icon of root node this.setState(this.rootNode,this.item.IsVisibleContentView); }, focusNodeById: function(/* objectid */id) { // summary: expands & selects node in tree var currentItem = this.model.store.fetchItemByIdentity(id); var path = [id]; while (currentItem.objectId != this.model.query.id) { currentItem = this.model.store.fetchItemByIdentity(currentItem.parentId); if(currentItem == undefined){ return; } path.unshift(currentItem.objectId); } this.item.parentId = undefined; for( var i=0,iLength=path.length ; i<iLength ; i++ ) { var objectId = path[i]; var node = this._getNodeByObjectId(objectId); if(node.rootNode){ this._expandNode(node.rootNode); } else{ this._expandNode(node); } if (i == path.length - 1) { if(node.rootNode){ node = node.rootNode; this.item = this.model.store.fetchItemByIdentity(this.item.objectId); node.item = this.item; } window.setTimeout(dojo.hitch(this,this._onNodeFocus,node),20); epages.event.fire(node.labelNode, 'focus'); // timeout is needed, without timeout after reload the tree does not select the current element correct //caused problems in the ToolNewPage EPG-27243 window.setTimeout(function(){ epages.event.fire(node.labelNode, 'click'); },1); dojo.publish(this.id+'/select',[node]); if(epages && epages.vars){ epages.vars.currentSelectedObjectID = node.item.objectId; } } } }, focusNode: function(node) { this._onNodeFocus(node); }, _onNodeFocus: function(/*dijit._Widget*/ node){ // summary: // Called when a TreeNode gets focus, either by user clicking // it, or programatically by arrow key handling code. // description: // It marks that the current node is the selected one, and the previously // selected node no longer is. if(node){ if(node != this.lastFocused && this.lastFocused && !this.lastFocused._destroyed){ // mark that the previously selected node is no longer the selected one this.blurNode(); this.lastFocused.setSelected(false); } // mark that the new node is the currently selected one dojo.addClass(node.labelNode,"Selected"); node.setSelected(true); this.lastFocused = node; } }, blurNode: function() { var node = this.lastFocused; if(!node){ return; } var labelNode = node.labelNode; dojo.removeClass(labelNode, "Selected"); labelNode.setAttribute("tabIndex", "-1"); }, onClick: function(item, node){ if(item && item.children !== undefined){ this._expandNode(node); this.setChildrenState(node); } dojo.publish(this.id+'/select',[node]); if(epages && epages.vars){ epages.vars.currentSelectedObjectID = node.item.objectId; } //if item with to many children error was clicked restore expand node var item = this.model.store.fetchItemByIdentity(node.item.objectId); if(item.error && item.error == 'ERROR_TOO_MANY_CHILDREN'){ node.state = "UNCHECKED"; node.isExpandable = true; node._setExpando(false); } // use jquery to release event in top frame (force blur for active CKEditors) top.jq('body').trigger("click"); }, selectNodeByObjectId : function(/* string */ objectId) { // summary: select a tree node by object id var node = this._getNodeByObjectId(objectId); this.onClick(node.item, node.rootNode ? node.rootNode : node); }, currentItem: function(){ return this.lastFocused.item; }, currentObjectID: function(){ return this.lastFocused.item.objectId; }, deleteCurrent: function() { var node = this.lastFocused; //treenode cant't be delete if (node === undefined || node.rootNode || node.item.ClassAlias == "StartPage" || node.item.isProduct == true){ return; } if(this.model.store.deleteItem(node.item)){ node.domNode.style.display = "none"; } var parentNode = node.getParent(); if(parentNode){ this._onNodeFocus(parentNode); dojo.publish(this.id+'/select',[parentNode]); if(epages && epages.vars){ epages.vars.currentSelectedObjectID = parentNode.item.objectId; } var children = parentNode.getChildren(); var visible = false; for( var i=0,iLength=children.length ; i<iLength ; i++ ){ if(children[i].domNode.style.display != "none"){ visible = true; } } if(visible != true){ parentNode.isExpandable = false; parentNode.isExpanded = false; parentNode._setExpando(false); } } }, moveUpCurrent: function () { var node = this.lastFocused; //can not move (tree node) or products if (node === undefined || node.rootNode || node.item.isProduct){ return; } if(this.model.store.moveItem(-1,node.item)){ var parentWidget = node.getParent(); var TreeNodes = parentWidget.getChildren(); var index = $A(TreeNodes).find(node); $A(TreeNodes).insertAt(index-1,node); $A(TreeNodes).remove(index+1); $A(TreeNodes).each(function(el) { parentWidget.addChild(el); }); this._onNodeFocus(node); } }, moveDownCurrent: function () { var node = this.lastFocused; //can not move (tree node) or products if (node === undefined || node.rootNode || node.item.isProduct){ return; } if(this.model.store.moveItem( 1,node.item)){ var parentWidget = node.getParent(); var TreeNodes = parentWidget.getChildren(); var index = $A(TreeNodes).find(node); $A(TreeNodes).insertAt(index+2,node); $A(TreeNodes).remove(index); $A(TreeNodes).each(function(el) { parentWidget.addChild(el); }); this._onNodeFocus(node); } }, _onStoreChangePosition: function(opt){ var node = this._getNodeByObjectId(opt.item.objectId); var newPosition = opt.item.position; var oldPosition = opt.oldPosition; var parentWidget = node.getParent(); var treeNodes = parentWidget.getChildren(); var treeNodesArray = $A(treeNodes); //find old Position in ChildrenArray var index = treeNodesArray.find(node); if(oldPosition == newPosition){ this._reloadTree(); return; } if(oldPosition > newPosition){ //move up if(index == 0){ console.warn('first in Array can not move up'); } else{ //insert one element before and remove old element treeNodesArray.insertAt(index-1,node); treeNodesArray.remove(index+1); } } if(oldPosition < newPosition){ //move down //insert one element after and remove old element treeNodesArray.insertAt(index+2,node); treeNodesArray.remove(index); } treeNodesArray.each(function(el) { parentWidget.addChild(el); }); }, _reloadNode: function(node){ if(node.isExpanded == true){ this._collapseNode(node); } node.state = "UNCHECKED"; if(node.item.children && node.item.children.length > 0){ node.isExpandable = true; node._setExpando(false); this._expandNode(node); } else{ node.isExpandable = false; node._setExpando(false); } this.setState(node,node.item.IsVisibleContentView); }, _reloadTree: function(noFocus){ var lastId = (this.lastFocused) ? this.lastFocused.item.objectId : undefined; this._itemNodesMap = {}; this.rootNode.item = this.model.store.fetchItemByIdentity(this.rootNode.item.objectId, true); this._reloadNode(this.rootNode); if(lastId && !noFocus){ this.focusNodeById(lastId); } }, _getNodeByObjectId: function(objectId, parentNode) { if (parentNode == undefined){ parentNode = this.rootNode; } if(objectId == this.item.objectId){ return this; } var nodesWithChildren = []; var children = parentNode.getChildren(); for( var i=0,iLength=children.length ; i<iLength ; i++ ) { var node = children[i]; if (node.item.objectId == objectId){ return node; } if (node.getChildren() && node.getChildren().length > 0){ nodesWithChildren.push(node); } } for( var i=0,iLength=nodesWithChildren.length ; i<iLength ; i++ ) { var node = this._getNodeByObjectId(objectId, nodesWithChildren[i]); if (node != null){ return node; } } return null; }, _onStoreChangeParent: function(opt){ var node = this._getNodeByObjectId(opt.item.objectId); if(!node){ //console.debug('cant find node'); return; } if(opt['delete']){ node.domNode.style.display = 'none'; var parentNode = node.getParent(); if(parentNode){ this._onNodeFocus(parentNode); dojo.publish(this.id+'/select',[parentNode]); } return; } //if Old Parent and New Parent equal than the it was an undo delete if(opt.oldParent == opt.item.parentId){ node.domNode.style.display = ''; return; } var oldParentNode = this._getNodeByObjectId(opt.oldParent); var newParentNode = this._getNodeByObjectId(opt.item.parentId); if(oldParentNode.rootNode){ this._indentNode(node,newParentNode,oldParentNode.rootNode); } else if(newParentNode.rootNode){ this._outdentNode(node,newParentNode.rootNode,oldParentNode); } else{ if($A(newParentNode.item.children).exists(oldParentNode.item.objectId)){ this._outdentNode(node,newParentNode,oldParentNode); } if($A(oldParentNode.item.children).exists(newParentNode.item.objectId)){ this._indentNode(node,newParentNode,oldParentNode); } } }, _indentNode: function(node,newParentNode,oldParentNode){ newParentNode.item = this.model.store.fetchItemByIdentity(newParentNode.item.objectId); oldParentNode.item = this.model.store.fetchItemByIdentity(oldParentNode.item.objectId); this._reloadNode(newParentNode); this._reloadNode(oldParentNode); var objectId = node.item.objectId; var newNode = this._getNodeByObjectId(objectId); this._onNodeFocus(newNode); }, indentCurrent: function () { var node = this.lastFocused; //can not indent (tree node) or products if (node === undefined || node.rootNode || node.item.isProduct){ return; } var oldParentNode = this._getNodeByObjectId(node.item.parentId); if(oldParentNode.rootNode){ oldParentNode = oldParentNode.rootNode; } var newParentObjectId = this.model.store.indentItem(node.item); if(newParentObjectId){ var newParentNode = this._getNodeByObjectId(newParentObjectId); // Flag to decide if a node is indented or outdented this.model.store.indentNode = true; this._indentNode(node,newParentNode,oldParentNode); } else{ console.warn('can not ident'); } }, _outdentNode: function(node,newParentNode,oldParentNode){ this._reloadNode(newParentNode); this._reloadNode(oldParentNode); var objectId = node.item.objectId; var newNode = this._getNodeByObjectId(objectId); this._onNodeFocus(newNode); }, outdentCurrent: function () { var node = this.lastFocused; // can not outdent tree node (start page) if (node === undefined || node.rootNode || node.item.isProduct){ return; } // can not outdent first level var oldParentNode = this._getNodeByObjectId(node.item.parentId); if (oldParentNode == undefined || oldParentNode.rootNode){ return; } // find position of parent to insert node behind var newParentObjectId = this.model.store.outdentItem(node.item); if(newParentObjectId){ var newParentNode = this._getNodeByObjectId(newParentObjectId); // Flag to decide if a node is indented or outdented this.model.store.indentNode = true; if(!newParentNode || newParentNode.rootNode){ newParentNode = this.rootNode; } this._outdentNode(node,newParentNode,oldParentNode); } }, createObject: function (/* form element */ classNode, /* form element */ nameNode, /* string? */ enterNameMessage, /* string? */ insertParentObjectId,isVisible) { // summary: // create a new object // classNode: // form element with class node id // nameNode: // form element with object name // enterNameMessage: // possibility to pass e debug message if nameNode value is empty // insertParentObjectId: // specify a different parent object var node = this.lastFocused; if (node === undefined){ return; } var objectId = undefined; if(node.item){ objectId = node.item.objectId; } else{ if(node.rootNode){ objectId = this.model.store.objectId; } } if(insertParentObjectId && this.model.store.fetchItemByIdentity(insertParentObjectId)) { // override current parent object objectId = insertParentObjectId; } if(!objectId){ return; } var name = $E(nameNode).get(); var classId = $E(classNode).get(); if (name == '') { if (enterNameMessage == ''){ enterNameMessage = 'Enter a name !'; } console.warn(enterNameMessage); return; } newItem = this.model.store.createObject(objectId, classId, name,isVisible); if(newItem){ node.item = this.model.store.fetchItemByIdentity(node.item.objectId); if(!node.isExpandable){ node.makeExpandable(); } this._reloadTree(true); //check if all children of parent are visible (not marked as deleted) var children = node.getChildren(); for( var i=0,iLength=children.length ; i<iLength ; i++ ){ //correct is deleted after reload if($('parentInput_'+children[i].item.objectId) && $('parentInput_'+children[i].item.objectId).value == 'Delete'){ children[i].item.isDeleted = true; } if(children[i].item.isDeleted == true){ children[i].domNode.style.display = 'none'; } } var newNode = this._getNodeByObjectId(newItem.objectId); this.focusNodeById(newItem.objectId); } else { console.warn('unable to created object in '+ this.declaredClass); } }, getIconClass: function(/*dojo.data.Item*/ item){ return item.persistentIconClass || ''; }, getLabelClass: function(/*dojo.data.Item*/ item){ // summary: user overridable function to return CSS class name to display label // description: if no return value is set dojo adds a class "undefined" to every label in the tree // tags: extendable return ''; }, setChildrenState: function(node){ var children = node.getChildren(); for( var i=0,iLength=children.length ; i<iLength ; i++ ){ this.setState(children[i],children[i].item.IsVisibleContentView); } }, setState: function(node,IsVisibleContentView){ IsVisibleContentView = parseInt(IsVisibleContentView); var item = node.item; if(node.rootNode){ item =this.item; node = node.rootNode; } //remove class Icon of IconNode if Node has no ClassAlias and is not a product if(!item.ClassAlias && !item.isProduct){ dojo.removeClass(node.iconNode,"Icon"); } else{ var iconSpriteName = epages.cartridges.de_epages.presentation.icon.getIconSpriteName(item.ClassAlias, IsVisibleContentView, item.isProduct); dojo.addClass(node.iconNode, "Sprite"); dojo.removeClass(node.iconNode, iconSpriteName + "_inactive"); dojo.addClass(node.iconNode, iconSpriteName); } if(IsVisibleContentView) { dojo.removeClass(node.contentNode,"NotVisible"); }else { dojo.addClass(node.contentNode,"NotVisible"); } item.persistentIconClass = node.iconNode.className; }, changeVisibilityCurrent: function(){ var node = this.lastFocused; if (node === undefined){ return; } node.item.IsVisibleContentView = this.model.store.changeVisibility(node.item); this.setState(node,node.item.IsVisibleContentView); dojo.publish(this.id+'/changeCurrentVisibility',[node]); }, _onStoreChangeVisibility: function(opt){ var node = this._getNodeByObjectId(opt.item.objectId); var IsVisibleContentView = parseInt(opt.item.IsVisibleContentView); this.setState(node,IsVisibleContentView); if(node == this.lastFocused){ dojo.publish(this.id+'/changeCurrentVisibility',[node]); } }, currentItem: function(){ return this.lastFocused.item; }, onOpen: function(item,node){ // add childNodes to childArray of item var childNodes = node.getChildren(); var itemChildArray = node.item.children; for( var i=0,iLength=childNodes.length ; i<iLength ; i++ ){ if(childNodes[i].item && childNodes[i].item.objectId){ var childId = childNodes[i].item.objectId; if(!$A(itemChildArray).exists(childId)){ node.item.children.push(childId); } } } }, _onExpandoClick: function(/*Object*/ message){ // summary: user clicked the +/- icon; expand or collapse my children. var node = message.node; // If we are collapsing, we might be hiding the currently focused node. // Also, clicking the expando node might have erased focus from the current node. // For simplicity's sake just focus on the node with the expando. if(node.isExpanded){ this._collapseNode(node); }else{ this._expandNode(node); this.setChildrenState(node); } //if a node with too many children was expanded the server gives an error code //check this code and show warning if necessary var item = this.model.store.fetchItemByIdentity(node.item.objectId); if(item.error && item.error == 'ERROR_TOO_MANY_CHILDREN'){ this._showManyChildrenWarning(this.item.objectId); } }, _showManyChildrenWarning: function(id){ //summary: shows warning if selected item has too many children to show var currentObjectLink = '<br /><br /><a link class="DialogAction" style="font-weight:bold" onclick="window.location.href=\'?ObjectID='+id+'&ViewAction=MBO-ViewGeneral\'" >'+this._translation.get('OpenDatasheetView')+'</a>'; dojo.publish("uimessage/show", [ this._translation.get('TooManyChildrenWarning'), this._translation.get('TooManyChildrenHint') + currentObjectLink, 'Dialog', { titleBar: this._translation.get('Notification'), typeClass: 'Notification' }]); } } );