/*
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.TreeV3");
dojo.require("dojo.widget.TreeWithNode");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.TreeNodeV3");
dojo.widget.defineWidget(
"dojo.widget.TreeV3",
[dojo.widget.HtmlWidget, dojo.widget.TreeWithNode],
function() {
this.eventNames = {};
this.DndAcceptTypes = [];
this.actionsDisabled = [];
this.listeners = [];
this.tree = this;
},
{
DndMode: "",
/**
* factory to generate default widgets
*/
defaultChildWidget: null,
defaultChildTitle: "New Node", // for editing
eagerWidgetInstantiation: false,
eventNamesDefault: {
// tree created.. Perform tree-wide actions if needed
afterTreeCreate: "afterTreeCreate",
beforeTreeDestroy: "beforeTreeDestroy",
/* can't name it "beforeDestroy", because such name causes memleaks in IE */
beforeNodeDestroy: "beforeNodeDestroy",
afterChangeTree: "afterChangeTree",
afterSetFolder: "afterSetFolder",
afterUnsetFolder: "afterUnsetFolder",
beforeMoveFrom: "beforeMoveFrom",
beforeMoveTo: "beforeMoveTo",
afterMoveFrom: "afterMoveFrom",
afterMoveTo: "afterMoveTo",
afterAddChild: "afterAddChild",
afterDetach: "afterDetach",
afterExpand: "afterExpand",
beforeExpand: "beforeExpand",
afterSetTitle: "afterSetTitle",
afterCollapse: "afterCollapse",
beforeCollapse: "beforeCollapse"
},
classPrefix: "Tree",
style: "",
/**
* is it possible to add a new child to leaf ?
*/
allowAddChildToLeaf: true,
/**
* when last children is removed from node should it stop being a "folder" ?
*/
unsetFolderOnEmpty: true,
DndModes: {
BETWEEN: 1,
ONTO: 2
},
DndAcceptTypes: "",
// will have cssRoot before it
templateCssPath: dojo.uri.dojoUri("src/widget/templates/TreeV3.css"),
templateString: '
\n
',
isExpanded: true, // consider this "root node" to be always expanded
isTree: true,
createNode: function(data) {
data.tree = this.widgetId;
if (data.widgetName) {
// TODO: check if such widget has createSimple
return dojo.widget.createWidget(data.widgetName, data);
} else if (this.defaultChildWidget.prototype.createSimple) {
return this.defaultChildWidget.prototype.createSimple(data);
} else {
var ns = this.defaultChildWidget.prototype.ns;
var wt = this.defaultChildWidget.prototype.widgetType;
return dojo.widget.createWidget(ns + ":" + wt, data);
}
},
// expandNode has +- CSS background. Not img.src for performance, background src string resides in single place.
// selection in KHTML/Mozilla disabled treewide, IE requires unselectable for every node
// you can add unselectable if you want both in postCreate of tree and in this template
// create new template and put into prototype
makeNodeTemplate: function() {
var domNode = document.createElement("div");
dojo.html.setClass(domNode, this.classPrefix+"Node "+this.classPrefix+"ExpandLeaf "+this.classPrefix+"ChildrenNo");
this.nodeTemplate = domNode;
var expandNode = document.createElement("div");
var clazz = this.classPrefix+"Expand";
if (dojo.render.html.ie) {
clazz = clazz + ' ' + this.classPrefix+"IEExpand";
}
dojo.html.setClass(expandNode, clazz);
this.expandNodeTemplate = expandNode;
// need inside
// div for multiline support, span for styling exactly the text, not whole line
var labelNode = document.createElement("span");
dojo.html.setClass(labelNode, this.classPrefix+"Label");
this.labelNodeTemplate = labelNode;
var contentNode = document.createElement("div");
var clazz = this.classPrefix+"Content";
/**
* IE<7 does not support min-height properly so I have to rely
* on this hack
* FIXME: do it in CSS only
*/
if (dojo.render.html.ie && !dojo.render.html.ie70) {
clazz = clazz + ' ' + this.classPrefix+"IEContent";
}
dojo.html.setClass(contentNode, clazz);
this.contentNodeTemplate = contentNode;
domNode.appendChild(expandNode);
domNode.appendChild(contentNode);
contentNode.appendChild(labelNode);
},
makeContainerNodeTemplate: function() {
var div = document.createElement('div');
div.style.display = 'none';
dojo.html.setClass(div, this.classPrefix+"Container");
this.containerNodeTemplate = div;
},
actions: {
ADDCHILD: "ADDCHILD"
},
getInfo: function() {
var info = {
widgetId: this.widgetId,
objectId: this.objectId
}
return info;
},
adjustEventNames: function() {
for(var name in this.eventNamesDefault) {
if (dojo.lang.isUndefined(this.eventNames[name])) {
this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
}
}
},
adjustDndMode: function() {
var _this = this;
var DndMode = 0;
dojo.lang.forEach(this.DndMode.split(';'),
function(elem) {
var mode = _this.DndModes[dojo.string.trim(elem).toUpperCase()];
if (mode) DndMode = DndMode | mode;
}
);
this.DndMode = DndMode;
},
/**
* publish destruction event so that any listeners should stop listening
*/
destroy: function() {
dojo.event.topic.publish(this.tree.eventNames.beforeTreeDestroy, { source: this } );
return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
},
initialize: function(args){
this.domNode.widgetId = this.widgetId;
for(var i=0; i