All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.custom.dojo.resource.src.widget.Tree.js Maven / Gradle / Ivy

/*
	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
*/

/**
 * Tree model does all the drawing, visual node management etc.
 * Throws events about clicks on it, so someone may catch them and process
 * Tree knows nothing about DnD stuff, covered in TreeDragAndDrop and (if enabled) attached by controller
*/

/**
 * TODO: use domNode.cloneNode instead of createElement for grid
 * Should be faster (lyxsus)
 */
dojo.provide("dojo.widget.Tree");

dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.TreeNode");
dojo.require("dojo.html.common");
dojo.require("dojo.html.selection");


dojo.widget.defineWidget("dojo.widget.Tree", dojo.widget.HtmlWidget, function() {
	this.eventNames = {};

	this.tree = this;
	this.DNDAcceptTypes = [];
	this.actionsDisabled = [];

},
{
	widgetType: "Tree",

	eventNamesDefault: {
		// new child does not get domNode filled in (only template draft)
		// until addChild->createDOMNode is called(program way) OR createDOMNode (html-way)
		// hook events to operate on new DOMNode, create dropTargets etc
		createDOMNode: "createDOMNode",
		// tree created.. Perform tree-wide actions if needed
		treeCreate: "treeCreate",
		treeDestroy: "treeDestroy",
		// expand icon clicked
		treeClick: "treeClick",
		// node icon clicked
		iconClick: "iconClick",
		// node title clicked
		titleClick: "titleClick",

		moveFrom: "moveFrom",
		moveTo: "moveTo",
		addChild: "addChild",
		removeNode: "removeNode",
		expand: "expand",
		collapse: "collapse"
	},

	isContainer: true,

	DNDMode: "off",

	lockLevel: 0, // lock ++ unlock --, so nested locking works fine

	strictFolders: true,

	DNDModes: {
		BETWEEN: 1,
		ONTO: 2
	},

	DNDAcceptTypes: "",

	templateCssPath: dojo.uri.dojoUri("src/widget/templates/images/Tree/Tree.css"),

	templateString: '
', isExpanded: true, // consider this "root node" to be always expanded isTree: true, objectId: "", // autoCreate if not "off" // used to get the autocreated controller ONLY. // generally, tree DOES NOT KNOW about its CONTROLLER, it just doesn't care // controller gets messages via dojo.event controller: "", // autoCreate if not "off" // used to get the autocreated selector ONLY. // generally, tree DOES NOT KNOW its SELECTOR // binding is made with dojo.event selector: "", // used ONLY at initialization time menu: "", // autobind menu if menu's widgetId is set here expandLevel: "", // expand to level automatically // // these icons control the grid and expando buttons for the whole tree // blankIconSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_blank.gif"), gridIconSrcT: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_t.gif"), // for non-last child grid gridIconSrcL: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_l.gif"), // for last child grid gridIconSrcV: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_v.gif"), // vertical line gridIconSrcP: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_p.gif"), // for under parent item child icons gridIconSrcC: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_c.gif"), // for under child item child icons gridIconSrcX: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_x.gif"), // grid for sole root item gridIconSrcY: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_y.gif"), // grid for last rrot item gridIconSrcZ: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_z.gif"), // for under root parent item child icon expandIconSrcPlus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_plus.gif"), expandIconSrcMinus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_minus.gif"), expandIconSrcLoading: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_loading.gif"), iconWidth: 18, iconHeight: 18, // // tree options // showGrid: true, showRootGrid: true, actionIsDisabled: function(action) { var _this = this; return dojo.lang.inArray(_this.actionsDisabled, action) }, actions: { ADDCHILD: "ADDCHILD" }, getInfo: function() { var info = { widgetId: this.widgetId, objectId: this.objectId } return info; }, initializeController: function() { if (this.controller != "off") { if (this.controller) { this.controller = dojo.widget.byId(this.controller); } else { // create default controller here dojo.require("dojo.widget.TreeBasicController"); this.controller = dojo.widget.createWidget("TreeBasicController", { DNDController: (this.DNDMode ? "create" : ""), dieWithTree: true } ); } this.controller.listenTree(this); // controller listens to my events } else { this.controller = null; } }, initializeSelector: function() { if (this.selector != "off") { if (this.selector) { this.selector = dojo.widget.byId(this.selector); } else { // create default controller here dojo.require("dojo.widget.TreeSelector"); this.selector = dojo.widget.createWidget("TreeSelector", {dieWithTree: true}); } this.selector.listenTree(this); } else { this.selector = null; } }, initialize: function(args, frag){ var _this = this; for(name in this.eventNamesDefault) { if (dojo.lang.isUndefined(this.eventNames[name])) { this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name]; } } for(var i=0; i no createDOMNode => no createDOMNode event domNodeInitialized: child.domNodeInitialized } this.doAddChild.apply(this, arguments); dojo.event.topic.publish(this.tree.eventNames.addChild, message); }, // not called for initial tree building. See createDOMNode instead. // builds child html node if needed // index is "last node" by default /** * FIXME: Is it possible that removeNode from the tree will cause leaks cause of attached events ? * if yes, then only attach events in addChild and detach in remove.. Seems all ok yet. */ doAddChild: function(child, index){ if (dojo.lang.isUndefined(index)) { index = this.children.length; } if (!child.isTreeNode){ dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!"); return; } // usually it is impossible to change "isFolder" state, but if anyone wants to add a child to leaf, // it is possible program-way. if (this.isTreeNode){ if (!this.isFolder) { // just became a folder. //dojo.debug("becoming folder "+this); this.setFolder(); } } // adjust tree var _this = this; dojo.lang.forEach(child.getDescendants(), function(elem) { elem.tree = _this.tree; }); // fix parent child.parent = this; // no dynamic loading for those who become parents if (this.isTreeNode) { this.state = this.loadStates.LOADED; } // add new child into DOM after it was added into children if (index < this.children.length) { // children[] already has child //dojo.debug("Inserting before "+this.children[index].title); dojo.html.insertBefore(child.domNode, this.children[index].domNode); } else { this.containerNode.appendChild(child.domNode); if (this.isExpanded && this.isTreeNode) { /* When I add children to hidden containerNode => show container w/ them */ this.showChildren(); } } this.children.splice(index, 0, child); //dojo.debugShallow(this.children); // if node exists - adjust its depth, otherwise build it if (child.domNodeInitialized) { var d = this.isTreeNode ? this.depth : -1; child.adjustDepth( d - child.depth + 1 ); // update icons to link generated dom with Tree => updateParentGrid // if I moved child from LastNode inside the tree => need to link it up'n'down => // updateExpandGridColumn // if I change depth => need to update all grid.. child.updateIconTree(); } else { //dojo.debug("Create domnode "); child.depth = this.isTreeNode ? this.depth+1 : 0; child.createDOMNode(child.tree, child.depth); } // Use-case: // When previous sibling was created => it was last, no children after it // so it did not create link down => let's add it for all descendants // Use-case: // a child was moved down under the last node so last node should be updated var prevSibling = child.getPreviousSibling(); if (child.isLastChild() && prevSibling) { prevSibling.updateExpandGridColumn(); } //dojo.debug("Added child "+child); }, makeBlankImg: function() { var img = document.createElement('img'); img.style.width = this.iconWidth + 'px'; img.style.height = this.iconHeight + 'px'; img.src = this.blankIconSrc; img.style.verticalAlign = 'middle'; return img; }, updateIconTree: function(){ //dojo.debug("Update icons for "+this) if (!this.isTree) { this.updateIcons(); } for(var i=0; i0) { children[index-1].updateExpandGridColumn(); } // if it WAS first node in WHOLE TREE - // update link up of its former lower neighbour(if exists still) if (parent instanceof dojo.widget.Tree && index == 0 && children.length>0) { children[0].updateExpandGrid(); } //parent.updateIconTree(); child.parent = child.tree = null; return child; }, markLoading: function() { // no way to mark tree loading }, unMarkLoading: function() { // no way to show that tree finished loading }, lock: function() { !this.lockLevel && this.markLoading(); this.lockLevel++; }, unlock: function() { if (!this.lockLevel) { dojo.raise("unlock: not locked"); } this.lockLevel--; !this.lockLevel && this.unMarkLoading(); }, isLocked: function() { var node = this; while (true) { if (node.lockLevel) { return true; } if (node instanceof dojo.widget.Tree) { break; } node = node.parent; } return false; }, flushLock: function() { this.lockLevel = 0; this.unMarkLoading(); } });




© 2015 - 2024 Weber Informatics LLC | Privacy Policy