/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml */ dojo.provide("dojo.widget.TreeSelectorV3"); dojo.require("dojo.widget.HtmlWidget"); dojo.require("dojo.widget.TreeCommon"); dojo.widget.defineWidget( "dojo.widget.TreeSelectorV3", [dojo.widget.HtmlWidget, dojo.widget.TreeCommon], function() { this.eventNames = {}; this.listenedTrees = {}; this.selectedNodes = []; this.lastClicked = {} }, { // TODO: add multiselect listenTreeEvents: ["afterTreeCreate","afterCollapse","afterChangeTree", "afterDetach", "beforeTreeDestroy"], listenNodeFilter: function(elem) { return elem instanceof dojo.widget.Widget}, allowedMulti: true, /** * if time between clicks < dblselectTimeout => its dblselect */ dblselectTimeout: 300, eventNamesDefault: { select : "select", deselect : "deselect", dblselect: "dblselect" // select already selected node.. Edit or whatever }, onAfterTreeCreate: function(message) { var tree = message.source; dojo.event.browser.addListener(tree.domNode, "onclick", dojo.lang.hitch(this, this.onTreeClick)); if (dojo.render.html.ie) { dojo.event.browser.addListener(tree.domNode, "ondblclick", dojo.lang.hitch(this, this.onTreeDblClick)); } dojo.event.browser.addListener(tree.domNode, "onKey", dojo.lang.hitch(this, this.onKey)); }, onKey: function(e) { if (!e.key || e.ctrkKey || e.altKey) { return; } switch(e.key) { case e.KEY_ENTER: var node = this.domElement2TreeNode(e.target); if (node) { this.processNode(node, e); } } }, onAfterChangeTree: function(message) { if (!message.oldTree && message.node.selected) { this.select(message.node); } if (!message.newTree || !this.listenedTrees[message.newTree.widgetId]) { // moving from our trfee to new one that we don't listen if (this.selectedNode && message.node.children) { this.deselectIfAncestorMatch(message.node); } } }, initialize: function(args) { for(name in this.eventNamesDefault) { if (dojo.lang.isUndefined(this.eventNames[name])) { this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name]; } } }, onBeforeTreeDestroy: function(message) { this.unlistenTree(message.source); }, // deselect node if ancestor is collapsed onAfterCollapse: function(message) { this.deselectIfAncestorMatch(message.source); }, // IE will throw select -> dblselect. Need to transform to select->select onTreeDblClick: function(event) { this.onTreeClick(event); }, checkSpecialEvent: function(event) { return event.shiftKey || event.ctrlKey; }, onTreeClick: function(event) { var node = this.domElement2TreeNode(event.target); if (!node) { return; } var checkLabelClick = function(domElement) { return domElement === node.labelNode; } if (this.checkPathCondition(event.target, checkLabelClick)) { this.processNode(node, event); } }, /** * press on selected with ctrl => deselect it * press on selected w/o ctrl => dblselect it and deselect all other * * press on unselected with ctrl => add it to selection * * event may be both mouse & keyboard enter */ processNode: function(node, event) { if (node.actionIsDisabled(node.actions.SELECT)) { return; } //dojo.debug("click "+node+ "special "+this.checkSpecialEvent(event)); if (dojo.lang.inArray(this.selectedNodes, node)) { if(this.checkSpecialEvent(event)){ // If the node is currently selected, and they select it again while holding // down a meta key, it deselects it this.deselect(node); return; } var _this = this; var i=0; var selectedNode; /* remove all nodes from selection excepts this one */ while(this.selectedNodes.length > i) { selectedNode = this.selectedNodes[i]; if (selectedNode !== node) { //dojo.debug("Deselect "+selectedNode); this.deselect(selectedNode); continue; } i++; // skip the doubleclicked node } /* lastClicked.node may be undefined if node was selected(before) programmatically */ var wasJustClicked = this.checkRecentClick(node) eventName = wasJustClicked ? this.eventNames.dblselect : this.eventNames.select; if (wasJustClicked) { eventName = this.eventNames.dblselect; /* after dblselect, next select is usual select */ this.forgetLastClicked(); } else { eventName = this.eventNames.select; this.setLastClicked(node) } dojo.event.topic.publish(eventName, { node: node }); return; } /* if unselected node.. */ this.deselectIfNoMulti(event); //dojo.debug("select"); this.setLastClicked(node); this.select(node); }, forgetLastClicked: function() { this.lastClicked = {} }, setLastClicked: function(node) { this.lastClicked.date = new Date(); this.lastClicked.node = node; }, checkRecentClick: function(node) { var diff = new Date() - this.lastClicked.date; //dojo.debug(new Date()) //dojo.debug("check old "+this.lastClicked.node+" now "+(new Date())+" diff "+diff) if (this.lastClicked.node && diff < this.dblselectTimeout) { return true; } else { return false; } }, // deselect all if no meta key or disallowed deselectIfNoMulti: function(event) { if (!this.checkSpecialEvent(event) || !this.allowedMulti) { //dojo.debug("deselect All"); this.deselectAll(); } }, deselectIfAncestorMatch: function(ancestor) { /* deselect all nodes with this ancestor */ var _this = this; dojo.lang.forEach(this.selectedNodes, function(node) { var selectedNode = node; node = node.parent while (node && node.isTreeNode) { //dojo.debug("ancestor try "+node); if (node === ancestor) { _this.deselect(selectedNode); return; } node = node.parent; } }); }, onAfterDetach: function(message) { this.deselectIfAncestorMatch(message.child); }, select: function(node) { var index = dojo.lang.find(this.selectedNodes, node, true); if (index >=0 ) { return; // already selected } //dojo.debug("select "+node); this.selectedNodes.push(node); dojo.event.topic.publish(this.eventNames.select, {node: node} ); }, deselect: function(node){ var index = dojo.lang.find(this.selectedNodes, node, true); if (index < 0) { //dojo.debug("not selected"); return; // not selected } //dojo.debug("deselect "+node); //dojo.debug((new Error()).stack); this.selectedNodes.splice(index, 1); dojo.event.topic.publish(this.eventNames.deselect, {node: node} ); //dojo.debug("deselect"); }, deselectAll: function() { //dojo.debug("deselect all "+this.selectedNodes); while (this.selectedNodes.length) { this.deselect(this.selectedNodes[0]); } } });