Subversion Repositories Applications.framework

Rev

Rev 159 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
159 jpm 1
/*----------------------------------------\
2
|      Cross Browser Tree Widget 1.1      |
3
|-----------------------------------------|
4
| Created by Emil A. Eklund (eae@eae.net) |
5
|    For WebFX (http://webfx.eae.net/)    |
6
|-----------------------------------------|
7
| This script is  provided as is  without |
8
| any warranty whatsoever. It may be used |
9
| free of charge for non commerical sites |
10
| For commerical use contact  the  author |
11
| of this script for further details.     |
12
|-----------------------------------------|
13
| Created 2000-12-11 | Updated 2001-09-06 |
14
\----------------------------------------*/
15
 
16
var webFXTreeConfig = {
17
	rootIcon        : 'media/images/empty.png',
18
	openRootIcon    : 'media/images/empty.png',
19
	folderIcon      : 'media/images/empty.png',
20
	openFolderIcon  : 'media/images/empty.png',
21
	fileIcon        : 'media/images/empty.png',
22
	iIcon           : 'media/images/I.png',
23
	lIcon           : 'media/images/L.png',
24
	lMinusIcon      : 'media/images/Lminus.png',
25
	lPlusIcon       : 'media/images/Lplus.png',
26
	tIcon           : 'media/images/T.png',
27
	tMinusIcon      : 'media/images/Tminus.png',
28
	tPlusIcon       : 'media/images/Tplus.png',
29
	blankIcon       : 'media/images/blank.png',
30
	defaultText     : 'Tree Item',
31
	defaultAction   : 'javascript:void(0);',
32
	defaultTarget   : 'right',
33
	defaultBehavior : 'classic'
34
};
35
 
36
var webFXTreeHandler = {
37
	idCounter : 0,
38
	idPrefix  : "webfx-tree-object-",
39
	all       : {},
40
	behavior  : null,
41
	selected  : null,
42
	getId     : function() { return this.idPrefix + this.idCounter++; },
43
	toggle    : function (oItem) { this.all[oItem.id.replace('-plus','')].toggle(); },
44
	select    : function (oItem) { this.all[oItem.id.replace('-icon','')].select(); },
45
	focus     : function (oItem) { this.all[oItem.id.replace('-anchor','')].focus(); },
46
	blur      : function (oItem) { this.all[oItem.id.replace('-anchor','')].blur(); },
47
	keydown   : function (oItem) { return this.all[oItem.id].keydown(window.event.keyCode); },
48
	cookies   : new WebFXCookie()
49
};
50
 
51
/*
52
 * WebFXCookie class
53
 */
54
 
55
function WebFXCookie() {
56
	if (document.cookie.length) { this.cookies = ' ' + document.cookie; }
57
}
58
 
59
WebFXCookie.prototype.setCookie = function (key, value) {
60
	document.cookie = key + "=" + escape(value);
61
}
62
 
63
WebFXCookie.prototype.getCookie = function (key) {
64
	if (this.cookies) {
65
		var start = this.cookies.indexOf(' ' + key + '=');
66
		if (start == -1) { return null; }
67
		var end = this.cookies.indexOf(";", start);
68
		if (end == -1) { end = this.cookies.length; }
69
		end -= start;
70
		var cookie = this.cookies.substr(start,end);
71
		return unescape(cookie.substr(cookie.indexOf('=') + 1, cookie.length - cookie.indexOf('=') + 1));
72
	}
73
	else { return null; }
74
}
75
 
76
/*
77
 * WebFXTreeAbstractNode class
78
 */
79
 
80
function WebFXTreeAbstractNode(sText, sAction, sTarget) {
81
	this.childNodes  = [];
82
	this.id     = webFXTreeHandler.getId();
83
	this.text   = sText || webFXTreeConfig.defaultText;
84
	this.action = sAction || webFXTreeConfig.defaultAction;
85
	this.targetWindow = sTarget || webFXTreeConfig.defaultTarget;
86
	this._last  = false;
87
	webFXTreeHandler.all[this.id] = this;
88
}
89
 
90
WebFXTreeAbstractNode.prototype.add = function (node) {
91
	node.parentNode = this;
92
	this.childNodes[this.childNodes.length] = node;
93
	var root = this;
94
	if (this.childNodes.length >=2) {
95
		this.childNodes[this.childNodes.length -2]._last = false;
96
	}
97
	while (root.parentNode) { root = root.parentNode; }
98
	if (root.rendered) {
99
		if (this.childNodes.length >= 2) {
100
			document.getElementById(this.childNodes[this.childNodes.length -2].id + '-plus').src = ((this.childNodes[this.childNodes.length -2].folder)?webFXTreeConfig.tMinusIcon:webFXTreeConfig.tIcon);
101
			if (this.childNodes[this.childNodes.length -2].folder) {
102
				this.childNodes[this.childNodes.length -2].plusIcon = webFXTreeConfig.tPlusIcon;
103
				this.childNodes[this.childNodes.length -2].minusIcon = webFXTreeConfig.tMinusIcon;
104
			}
105
			this.childNodes[this.childNodes.length -2]._last = false;
106
		}
107
		this._last = true;
108
		var foo = this;
109
		while (foo.parentNode) {
110
			for (var i = 0; i < foo.parentNode.childNodes.length; i++) {
111
				if (foo.id == foo.parentNode.childNodes[i].id) { break; }
112
			}
113
			if (++i == foo.parentNode.childNodes.length) { foo.parentNode._last = true; }
114
			else { foo.parentNode._last = false; }
115
			foo = foo.parentNode;
116
		}
117
		document.getElementById(this.id + '-cont').insertAdjacentHTML("beforeEnd", node.toString());
118
		if ((!this.folder) && (!this.openIcon)) {
119
			this.icon = webFXTreeConfig.folderIcon;
120
			this.openIcon = webFXTreeConfig.openFolderIcon;
121
		}
122
		this.folder = true;
123
		this.indent();
124
		this.expand();
125
	}
126
	return node;
127
}
128
 
129
WebFXTreeAbstractNode.prototype.toggle = function() {
130
	if (this.folder) {
131
		if (this.open) { this.collapse(); }
132
		else { this.expand(); }
133
	}
134
}
135
 
136
WebFXTreeAbstractNode.prototype.select = function() {
137
	document.getElementById(this.id + '-anchor').focus();
138
}
139
 
140
WebFXTreeAbstractNode.prototype.focus = function() {
141
	webFXTreeHandler.selected = this;
142
	if ((this.openIcon) && (webFXTreeHandler.behavior != 'classic')) { document.getElementById(this.id + '-icon').src = this.openIcon; }
143
	document.getElementById(this.id + '-anchor').style.backgroundColor = 'highlight';
144
	document.getElementById(this.id + '-anchor').style.color = 'highlighttext';
145
	document.getElementById(this.id + '-anchor').focus();
146
}
147
 
148
WebFXTreeAbstractNode.prototype.blur = function() {
149
	if ((this.openIcon) && (webFXTreeHandler.behavior != 'classic')) { document.getElementById(this.id + '-icon').src = this.icon; }
150
	document.getElementById(this.id + '-anchor').style.backgroundColor = 'transparent';
151
	document.getElementById(this.id + '-anchor').style.color = 'menutext';
152
}
153
 
154
WebFXTreeAbstractNode.prototype.doExpand = function() {
155
	if (webFXTreeHandler.behavior == 'classic') { document.getElementById(this.id + '-icon').src = this.openIcon; }
156
	if (this.childNodes.length) {  document.getElementById(this.id + '-cont').style.display = 'block'; }
157
	this.open = true;
158
	webFXTreeHandler.cookies.setCookie(this.id.substr(18,this.id.length - 18), '1');
159
}
160
 
161
WebFXTreeAbstractNode.prototype.doCollapse = function() {
162
	if (webFXTreeHandler.behavior == 'classic') { document.getElementById(this.id + '-icon').src = this.icon; }
163
	if (this.childNodes.length) { document.getElementById(this.id + '-cont').style.display = 'none'; }
164
	this.open = false;
165
	webFXTreeHandler.cookies.setCookie(this.id.substr(18,this.id.length - 18), '0');
166
}
167
 
168
WebFXTreeAbstractNode.prototype.expandAll = function() {
169
	this.expandChildren();
170
	if ((this.folder) && (!this.open)) { this.expand(); }
171
}
172
 
173
WebFXTreeAbstractNode.prototype.expandChildren = function() {
174
	for (var i = 0; i < this.childNodes.length; i++) {
175
		this.childNodes[i].expandAll();
176
} }
177
 
178
WebFXTreeAbstractNode.prototype.collapseAll = function() {
179
	if ((this.folder) && (this.open)) { this.collapse(); }
180
	this.collapseChildren();
181
}
182
 
183
WebFXTreeAbstractNode.prototype.collapseChildren = function() {
184
	for (var i = 0; i < this.childNodes.length; i++) {
185
		this.childNodes[i].collapseAll();
186
} }
187
 
188
WebFXTreeAbstractNode.prototype.indent = function(lvl, del, last, level) {
189
	/*
190
	 * Since we only want to modify items one level below ourself,
191
	 * and since the rightmost indentation position is occupied by
192
	 * the plus icon we set this to -2
193
	 */
194
	if (lvl == null) { lvl = -2; }
195
	var state = 0;
196
	for (var i = this.childNodes.length - 1; i >= 0 ; i--) {
197
		state = this.childNodes[i].indent(lvl + 1, del, last, level);
198
		if (state) { return; }
199
	}
200
	if (del) {
201
		if (level >= this._level) {
202
			if (this.folder) {
203
				document.getElementById(this.id + '-plus').src = (this.open)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.lPlusIcon;
204
				this.plusIcon = webFXTreeConfig.lPlusIcon;
205
				this.minusIcon = webFXTreeConfig.lMinusIcon;
206
			}
207
			else { document.getElementById(this.id + '-plus').src = webFXTreeConfig.lIcon; }
208
			return 1;
209
		}
210
	}
211
	var foo = document.getElementById(this.id + '-indent-' + lvl);
212
	if (foo) {
213
		if ((del) && (last)) { foo._last = true; }
214
		if (foo._last) { foo.src =  webFXTreeConfig.blankIcon; }
215
		else { foo.src =  webFXTreeConfig.iIcon; }
216
	}
217
	return 0;
218
}
219
 
220
/*
221
 * WebFXTree class
222
 */
223
 
224
function WebFXTree(sText, sAction, sBehavior, sIcon, sOpenIcon) {
225
	this.base = WebFXTreeAbstractNode;
226
	this.base(sText, sAction);
227
	this.icon      = sIcon || webFXTreeConfig.rootIcon;
228
	this.openIcon  = sOpenIcon || webFXTreeConfig.openRootIcon;
229
	/* Defaults to open */
230
	this.open      = (webFXTreeHandler.cookies.getCookie(this.id.substr(18,this.id.length - 18)) == '0')?false:true;
231
	this.folder    = true;
232
	this.rendered  = false;
233
	if (!webFXTreeHandler.behavior) {  webFXTreeHandler.behavior = sBehavior || webFXTreeConfig.defaultBehavior; }
234
	this.targetWindow = 'right';
235
}
236
 
237
WebFXTree.prototype = new WebFXTreeAbstractNode;
238
 
239
WebFXTree.prototype.setBehavior = function (sBehavior) {
240
	webFXTreeHandler.behavior =  sBehavior;
241
};
242
 
243
WebFXTree.prototype.getBehavior = function (sBehavior) {
244
	return webFXTreeHandler.behavior;
245
};
246
 
247
WebFXTree.prototype.getSelected = function() {
248
	if (webFXTreeHandler.selected) { return webFXTreeHandler.selected; }
249
	else { return null; }
250
}
251
 
252
WebFXTree.prototype.remove = function() { }
253
 
254
WebFXTree.prototype.expand = function() {
255
	this.doExpand();
256
}
257
 
258
WebFXTree.prototype.collapse = function() {
259
	this.focus();
260
	this.doCollapse();
261
}
262
 
263
WebFXTree.prototype.getFirst = function() {
264
	return null;
265
}
266
 
267
WebFXTree.prototype.getLast = function() {
268
	return null;
269
}
270
 
271
WebFXTree.prototype.getNextSibling = function() {
272
	return null;
273
}
274
 
275
WebFXTree.prototype.getPreviousSibling = function() {
276
	return null;
277
}
278
 
279
WebFXTree.prototype.keydown = function(key) {
280
	if (key == 39) { this.expand(); return false; }
281
	if (key == 37) { this.collapse(); return false; }
282
	if ((key == 40) && (this.open)) { this.childNodes[0].select(); return false; }
283
	return true;
284
}
285
 
286
WebFXTree.prototype.toString = function() {
287
	var str = "<div id=\"" + this.id + "\" ondblclick=\"webFXTreeHandler.toggle(this);\" class=\"webfx-tree-item\" onkeydown=\"return webFXTreeHandler.keydown(this)\">";
288
	str += "<img id=\"" + this.id + "-icon\" class=\"webfx-tree-icon\" src=\"" + ((webFXTreeHandler.behavior == 'classic' && this.open)?this.openIcon:this.icon) + "\" onclick=\"webFXTreeHandler.select(this);\"><a href=\"" + this.action + "\" id=\"" + this.id + "-anchor\" target=\"" + this.targetWindow + "\" onfocus=\"webFXTreeHandler.focus(this);\" onblur=\"webFXTreeHandler.blur(this);\">" + this.text + "</a></div>";
289
	str += "<div id=\"" + this.id + "-cont\" class=\"webfx-tree-container\" style=\"display: " + ((this.open)?'block':'none') + ";\">";
290
	for (var i = 0; i < this.childNodes.length; i++) {
291
		str += this.childNodes[i].toString(i, this.childNodes.length);
292
	}
293
	str += "</div>";
294
	this.rendered = true;
295
	return str;
296
};
297
 
298
/*
299
 * WebFXTreeItem class
300
 */
301
 
302
function WebFXTreeItem(sText, sAction, eParent, sIcon, sOpenIcon) {
303
	this.base = WebFXTreeAbstractNode;
304
	this.base(sText, sAction);
305
	/* Defaults to close */
306
	this.open = (webFXTreeHandler.cookies.getCookie(this.id.substr(18,this.id.length - 18)) == '1')?true:false;
307
	if (eParent) { eParent.add(this); }
308
	if (sIcon) { this.icon = sIcon; }
309
	if (sOpenIcon) { this.openIcon = sOpenIcon; }
310
}
311
 
312
WebFXTreeItem.prototype = new WebFXTreeAbstractNode;
313
 
314
WebFXTreeItem.prototype.remove = function() {
315
	var parentNode = this.parentNode;
316
	var prevSibling = this.getPreviousSibling(true);
317
	var nextSibling = this.getNextSibling(true);
318
	var folder = this.parentNode.folder;
319
	var last = ((nextSibling) && (nextSibling.parentNode) && (nextSibling.parentNode.id == parentNode.id))?false:true;
320
	this.getPreviousSibling().focus();
321
	this._remove();
322
	if (parentNode.childNodes.length == 0) {
323
		parentNode.folder = false;
324
		parentNode.open = false;
325
	}
326
	if (last) {
327
		if (parentNode.id == prevSibling.id) {
328
			document.getElementById(parentNode.id + '-icon').src = webFXTreeConfig.fileIcon;
329
		}
330
		else { }
331
	}
332
	if ((!prevSibling.parentNode) || (prevSibling.parentNode != parentNode)) {
333
		parentNode.indent(null, true, last, this._level);
334
	}
335
	if (document.getElementById(prevSibling.id + '-plus')) {
336
		if (nextSibling) {
337
			if ((parentNode == prevSibling) && (parentNode.getNextSibling))  { document.getElementById(prevSibling.id + '-plus').src = webFXTreeConfig.tIcon; }
338
			else if (nextSibling.parentNode != prevSibling) { document.getElementById(prevSibling.id + '-plus').src = webFXTreeConfig.lIcon; }
339
		}
340
		else { document.getElementById(prevSibling.id + '-plus').src = webFXTreeConfig.lIcon; }
341
	}
342
}
343
 
344
WebFXTreeItem.prototype._remove = function() {
345
	for (var i = this.childNodes.length - 1; i >= 0; i--) {
346
		this.childNodes[i]._remove();
347
 	}
348
	for (var i = 0; i < this.parentNode.childNodes.length; i++) {
349
		if (this.id == this.parentNode.childNodes[i].id) {
350
			for (var j = i; j < this.parentNode.childNodes.length; j++) {
351
				this.parentNode.childNodes[i] = this.parentNode.childNodes[i+1]
352
			}
353
			this.parentNode.childNodes.length = this.parentNode.childNodes.length - 1;
354
			if (i + 1 == this.parentNode.childNodes.length) { this.parentNode._last = true; }
355
		}
356
	}
357
	webFXTreeHandler.all[this.id] = null;
358
	if (document.getElementById(this.id)) {
359
		document.getElementById(this.id).innerHTML = "";
360
		document.getElementById(this.id).removeNode();
361
	}
362
}
363
 
364
WebFXTreeItem.prototype.expand = function() {
365
	this.doExpand();
366
	document.getElementById(this.id + '-plus').src = this.minusIcon;
367
}
368
 
369
WebFXTreeItem.prototype.collapse = function() {
370
	this.focus();
371
	this.doCollapse();
372
	document.getElementById(this.id + '-plus').src = this.plusIcon;
373
}
374
 
375
WebFXTreeItem.prototype.getFirst = function() {
376
	return this.childNodes[0];
377
}
378
 
379
WebFXTreeItem.prototype.getLast = function() {
380
	if (this.childNodes[this.childNodes.length - 1].open) { return this.childNodes[this.childNodes.length - 1].getLast(); }
381
	else { return this.childNodes[this.childNodes.length - 1]; }
382
}
383
 
384
WebFXTreeItem.prototype.getNextSibling = function() {
385
	for (var i = 0; i < this.parentNode.childNodes.length; i++) {
386
		if (this == this.parentNode.childNodes[i]) { break; }
387
	}
388
	if (++i == this.parentNode.childNodes.length) { return this.parentNode.getNextSibling(); }
389
	else { return this.parentNode.childNodes[i]; }
390
}
391
 
392
WebFXTreeItem.prototype.getPreviousSibling = function(b) {
393
	for (var i = 0; i < this.parentNode.childNodes.length; i++) {
394
		if (this == this.parentNode.childNodes[i]) { break; }
395
	}
396
	if (i == 0) { return this.parentNode; }
397
	else {
398
		if ((this.parentNode.childNodes[--i].open) || (b && this.parentNode.childNodes[i].folder)) { return this.parentNode.childNodes[i].getLast(); }
399
		else { return this.parentNode.childNodes[i]; }
400
} }
401
 
402
WebFXTreeItem.prototype.keydown = function(key) {
403
	if ((key == 39) && (this.folder)) {
404
		if (!this.open) { this.expand(); return false; }
405
		else { this.getFirst().select(); return false; }
406
	}
407
	else if (key == 37) {
408
		if (this.open) { this.collapse(); return false; }
409
		else { this.parentNode.select(); return false; }
410
	}
411
	else if (key == 40) {
412
		if (this.open) { this.getFirst().select(); return false; }
413
		else {
414
			var sib = this.getNextSibling();
415
			if (sib) { sib.select(); return false; }
416
	} }
417
	else if (key == 38) { this.getPreviousSibling().select(); return false; }
418
	return true;
419
}
420
 
421
WebFXTreeItem.prototype.toString = function (nItem, nItemCount) {
422
	var foo = this.parentNode;
423
	var indent = '';
424
	if (nItem + 1 == nItemCount) { this.parentNode._last = true; }
425
	var i = 0;
426
	while (foo.parentNode) {
427
		foo = foo.parentNode;
428
		indent = "<img id=\"" + this.id + "-indent-" + i + "\" src=\"" + ((foo._last)?webFXTreeConfig.blankIcon:webFXTreeConfig.iIcon) + "\">" + indent;
429
		i++;
430
	}
431
	this._level = i;
432
	if (this.childNodes.length) { this.folder = 1; }
433
	else { this.open = false; }
434
	if ((this.folder) || (webFXTreeHandler.behavior != 'classic')) {
435
		if (!this.icon) { this.icon = webFXTreeConfig.folderIcon; }
436
		if (!this.openIcon) { this.openIcon = webFXTreeConfig.openFolderIcon; }
437
	}
438
	else if (!this.icon) { this.icon = webFXTreeConfig.fileIcon; }
439
	var label = this.text;
440
	label = label.replace('<', '<');
441
	label = label.replace('>', '>');
442
	var str = "<div id=\"" + this.id + "\" ondblclick=\"webFXTreeHandler.toggle(this);\" class=\"webfx-tree-item\" onkeydown=\"return webFXTreeHandler.keydown(this)\">";
443
	str += indent;
444
	str += "<img id=\"" + this.id + "-plus\" src=\"" + ((this.folder)?((this.open)?((this.parentNode._last)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.tMinusIcon):((this.parentNode._last)?webFXTreeConfig.lPlusIcon:webFXTreeConfig.tPlusIcon)):((this.parentNode._last)?webFXTreeConfig.lIcon:webFXTreeConfig.tIcon)) + "\" onclick=\"webFXTreeHandler.toggle(this);\">"
445
	str += "<img id=\"" + this.id + "-icon\" src=\"" + ((webFXTreeHandler.behavior == 'classic' && this.open)?this.openIcon:this.icon) + "\" onclick=\"webFXTreeHandler.select(this);\"><a href=\"" + this.action + "\" id=\"" + this.id + "-anchor\" target=\"" + this.targetWindow + "\" onfocus=\"webFXTreeHandler.focus(this);\" onblur=\"webFXTreeHandler.blur(this);\">" + label + "</a></div>";
446
	str += "<div id=\"" + this.id + "-cont\" class=\"webfx-tree-container\" style=\"display: " + ((this.open)?'block':'none') + ";\">";
447
	for (var i = 0; i < this.childNodes.length; i++) {
448
		str += this.childNodes[i].toString(i,this.childNodes.length);
449
	}
450
	str += "</div>";
451
	this.plusIcon = ((this.parentNode._last)?webFXTreeConfig.lPlusIcon:webFXTreeConfig.tPlusIcon);
452
	this.minusIcon = ((this.parentNode._last)?webFXTreeConfig.lMinusIcon:webFXTreeConfig.tMinusIcon);
453
	return str;
454
}