1
|
/*----------------------------------------------------------------------------\
|
2
|
| XTree 2 PRE RELEASE |
|
3
|
| |
|
4
|
| This is a pre release and redistribution is discouraged. |
|
5
|
| Watch http://webfx.eae.net for the final version |
|
6
|
| |
|
7
|
|-----------------------------------------------------------------------------|
|
8
|
| Created by Erik Arvidsson & Emil A Eklund |
|
9
|
| (http://webfx.eae.net/contact.html#erik) |
|
10
|
| (http://webfx.eae.net/contact.html#emil) |
|
11
|
| For WebFX (http://webfx.eae.net/) |
|
12
|
|-----------------------------------------------------------------------------|
|
13
|
| A tree menu system for IE 5.5+, Mozilla 1.4+, Opera 7, KHTML |
|
14
|
|-----------------------------------------------------------------------------|
|
15
|
| Copyright (c) 1999 - 2005 Erik Arvidsson & Emil A Eklund |
|
16
|
|-----------------------------------------------------------------------------|
|
17
|
| This software is provided "as is", without warranty of any kind, express or |
|
18
|
| implied, including but not limited to the warranties of merchantability, |
|
19
|
| fitness for a particular purpose and noninfringement. In no event shall the |
|
20
|
| authors or copyright holders be liable for any claim, damages or other |
|
21
|
| liability, whether in an action of contract, tort or otherwise, arising |
|
22
|
| from, out of or in connection with the software or the use or other |
|
23
|
| dealings in the software. |
|
24
|
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
25
|
| This software is available under the three different licenses mentioned |
|
26
|
| below. To use this software you must chose, and qualify, for one of those. |
|
27
|
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
28
|
| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
|
29
|
| Permits anyone the right to use the software in a non-commercial context |
|
30
|
| free of charge. |
|
31
|
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
32
|
| The WebFX Commercial license http://webfx.eae.net/commercial.html |
|
33
|
| Permits the license holder the right to use the software in a commercial |
|
34
|
| context. Such license must be specifically obtained, however it's valid for |
|
35
|
| any number of implementations of the licensed software. |
|
36
|
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
37
|
| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
|
38
|
| Permits anyone the right to use and modify the software without limitations |
|
39
|
| as long as proper credits are given and the original and modified source |
|
40
|
| code are included. Requires that the final product, software derivate from |
|
41
|
| the original source or any software utilizing a GPL component, such as |
|
42
|
| this, is also licensed under the GPL license. |
|
43
|
|-----------------------------------------------------------------------------|
|
44
|
| 2004-02-21 | Pre release distributed to a few selected tester |
|
45
|
| 2005-06-06 | Added single tab index to improve keyboard navigation |
|
46
|
|-----------------------------------------------------------------------------|
|
47
|
| Dependencies: xtree2.css Used to define the look and feel |
|
48
|
|-----------------------------------------------------------------------------|
|
49
|
| Created 2003-??-?? | All changes are in the log above. | Updated 2004-06-06 |
|
50
|
\----------------------------------------------------------------------------*/
|
51
|
|
52
|
|
53
|
//
|
54
|
// WebFXTreePersisitance
|
55
|
function WebFXTreePersistence() {}
|
56
|
var _p = WebFXTreePersistence.prototype;
|
57
|
_p.getExpanded = function (oNode) { return false; };
|
58
|
_p.setExpanded = function (oNode, bOpen) {};
|
59
|
|
60
|
|
61
|
|
62
|
// Cookie handling
|
63
|
function WebFXCookie() {}
|
64
|
|
65
|
_p = WebFXCookie.prototype;
|
66
|
|
67
|
_p.setCookie = function (sName, sValue, nDays) {
|
68
|
var expires = "";
|
69
|
if (typeof nDays == "number") {
|
70
|
var d = new Date();
|
71
|
d.setTime(d.getTime() + nDays * 24 * 60 * 60 * 1000);
|
72
|
expires = "; expires=" + d.toGMTString();
|
73
|
}
|
74
|
|
75
|
document.cookie = sName + "=" + escape(sValue) + expires + "; path=/";
|
76
|
};
|
77
|
|
78
|
_p.getCookie = function (sName) {
|
79
|
var re = new RegExp("(\;|^)[^;]*(" + sName + ")\=([^;]*)(;|$)");
|
80
|
var res = re.exec(document.cookie);
|
81
|
return res != null ? unescape(res[3]) : null;
|
82
|
};
|
83
|
|
84
|
_p.removeCookie = function (name) {
|
85
|
this.setCookie(name, "", -1);
|
86
|
};
|
87
|
|
88
|
|
89
|
//
|
90
|
// persistence using cookies
|
91
|
//
|
92
|
// This is uses one cookie with the ids of the expanded nodes separated using '+'
|
93
|
//
|
94
|
function WebFXTreeCookiePersistence() {
|
95
|
this._openedMap = {};
|
96
|
this._cookies = new WebFXCookie;
|
97
|
var s = this._cookies.getCookie(this.cookieName);
|
98
|
if (s) {
|
99
|
var a = s.split("+");
|
100
|
for (var i = a.length - 1; i >= 0; i--)
|
101
|
this._openedMap[a[i]] = true;
|
102
|
}
|
103
|
}
|
104
|
|
105
|
_p = WebFXTreeCookiePersistence.prototype = new WebFXTreePersistence;
|
106
|
|
107
|
_p.cookieName = "webfx-tree-cookie-persistence"
|
108
|
|
109
|
_p.getExpanded = function (oNode) {
|
110
|
return oNode.id in this._openedMap;
|
111
|
};
|
112
|
|
113
|
_p.setExpanded = function (oNode, bOpen) {
|
114
|
var old = this.getExpanded(oNode);
|
115
|
if (old != bOpen) {
|
116
|
if (bOpen) {
|
117
|
this._openedMap[oNode.id] = true;
|
118
|
} else {
|
119
|
delete this._openedMap[oNode.id];
|
120
|
}
|
121
|
|
122
|
var res = [];
|
123
|
var i = 0;
|
124
|
for (var id in this._openedMap)
|
125
|
res[i++] = id;
|
126
|
this._cookies.setCookie(this.cookieName, res.join("+"));
|
127
|
}
|
128
|
};
|
129
|
|
130
|
|
131
|
|
132
|
// this object provides a few useful methods when working with arrays
|
133
|
var arrayHelper = {
|
134
|
indexOf: function (a, o) {
|
135
|
for (var i = 0; i < a.length; i++) {
|
136
|
if (a[i] == o) {
|
137
|
return i;
|
138
|
}
|
139
|
}
|
140
|
return -1;
|
141
|
},
|
142
|
|
143
|
insertBefore: function (a, o, o2) {
|
144
|
var i = this.indexOf(a, o2);
|
145
|
if (i == -1) {
|
146
|
a.push(o);
|
147
|
} else {
|
148
|
a.splice(i, 0, o);
|
149
|
}
|
150
|
},
|
151
|
|
152
|
remove: function (a, o) {
|
153
|
var i = this.indexOf(a, o);
|
154
|
if (i != -1) {
|
155
|
a.splice(i, 1);
|
156
|
}
|
157
|
}
|
158
|
};
|
159
|
|
160
|
///////////////////////////////////////////////////////////////////////////////
|
161
|
// WebFX Tree Config object //
|
162
|
///////////////////////////////////////////////////////////////////////////////
|
163
|
var webFXTreeConfig = {
|
164
|
rootIcon : "images/folder.png",
|
165
|
openRootIcon : "images/openfolder.png",
|
166
|
folderIcon : "images/folder.png",
|
167
|
openFolderIcon : "images/openfolder.png",
|
168
|
fileIcon : "images/file.png",
|
169
|
iIcon : "images/I.png",
|
170
|
lIcon : "images/L.png",
|
171
|
lMinusIcon : "images/Lminus.png",
|
172
|
lPlusIcon : "images/Lplus.png",
|
173
|
tIcon : "images/T.png",
|
174
|
tMinusIcon : "images/Tminus.png",
|
175
|
tPlusIcon : "images/Tplus.png",
|
176
|
plusIcon : "images/plus.png",
|
177
|
minusIcon : "images/minus.png",
|
178
|
blankIcon : "images/blank.png",
|
179
|
defaultText : "Tree Item",
|
180
|
defaultAction : null,
|
181
|
defaultBehavior : "classic",
|
182
|
usePersistence : true
|
183
|
};
|
184
|
|
185
|
///////////////////////////////////////////////////////////////////////////////
|
186
|
// WebFX Tree Handler object //
|
187
|
///////////////////////////////////////////////////////////////////////////////
|
188
|
|
189
|
var webFXTreeHandler = {
|
190
|
ie: /msie/i.test(navigator.userAgent),
|
191
|
opera: /opera/i.test(navigator.userAgent),
|
192
|
idCounter: 0,
|
193
|
idPrefix: "wfxt-",
|
194
|
getUniqueId: function () {
|
195
|
return this.idPrefix + this.idCounter++;
|
196
|
},
|
197
|
all: {},
|
198
|
getNodeById: function (sId) {
|
199
|
return all[sId];
|
200
|
},
|
201
|
addNode: function (oNode) {
|
202
|
this.all[oNode.id] = oNode;
|
203
|
},
|
204
|
removeNode: function (oNode) {
|
205
|
delete this.all[oNode.id];
|
206
|
},
|
207
|
|
208
|
handleEvent: function (e) {
|
209
|
var el = e.target || e.srcElement;
|
210
|
while (el != null && !this.all[el.id]) {
|
211
|
el = el.parentNode;
|
212
|
}
|
213
|
|
214
|
if (el == null) {
|
215
|
return false;
|
216
|
}
|
217
|
var node = this.all[el.id];
|
218
|
if (typeof node["_on" + e.type] == "function") {
|
219
|
return node["_on" + e.type](e);
|
220
|
}
|
221
|
return false;
|
222
|
},
|
223
|
|
224
|
dispose: function () {
|
225
|
if (this.disposed) return;
|
226
|
for (var id in this.all) {
|
227
|
this.all[id].dispose();
|
228
|
}
|
229
|
this.disposed = true;
|
230
|
},
|
231
|
|
232
|
htmlToText: function (s) {
|
233
|
return String(s).replace(/\s+|<([^>])+>|&|<|>|"| /gi, this._htmlToText);
|
234
|
},
|
235
|
|
236
|
_htmlToText: function (s) {
|
237
|
switch (s) {
|
238
|
case "&":
|
239
|
return "&";
|
240
|
case "<":
|
241
|
return "<";
|
242
|
case ">":
|
243
|
return ">";
|
244
|
case """:
|
245
|
return "\"";
|
246
|
case " ":
|
247
|
return String.fromCharCode(160);
|
248
|
default:
|
249
|
if (/\s+/.test(s)) {
|
250
|
return " ";
|
251
|
}
|
252
|
if (/^<BR/gi.test(s)) {
|
253
|
return "\n";
|
254
|
}
|
255
|
return "";
|
256
|
}
|
257
|
},
|
258
|
|
259
|
textToHtml: function (s) {
|
260
|
return String(s).replace(/&|<|>|\n|\"\u00A0/g, this._textToHtml);
|
261
|
},
|
262
|
|
263
|
_textToHtml: function (s) {
|
264
|
switch (s) {
|
265
|
case "&":
|
266
|
return "&";
|
267
|
case "<":
|
268
|
return "<";
|
269
|
case ">":
|
270
|
return ">";
|
271
|
case "\n":
|
272
|
return "<BR>";
|
273
|
case "\"":
|
274
|
return """; // so we can use this in attributes
|
275
|
default:
|
276
|
return " ";
|
277
|
}
|
278
|
},
|
279
|
|
280
|
persistenceManager: new WebFXTreeCookiePersistence()
|
281
|
};
|
282
|
|
283
|
|
284
|
///////////////////////////////////////////////////////////////////////////////
|
285
|
// WebFXTreeAbstractNode
|
286
|
///////////////////////////////////////////////////////////////////////////////
|
287
|
|
288
|
function WebFXTreeAbstractNode(sText, oAction) {
|
289
|
this.childNodes = [];
|
290
|
if (sText) this.text = sText;
|
291
|
if (oAction) this.action = oAction;
|
292
|
this.id = webFXTreeHandler.getUniqueId();
|
293
|
if (webFXTreeConfig.usePersistence) {
|
294
|
this.open = webFXTreeHandler.persistenceManager.getExpanded(this);
|
295
|
}
|
296
|
webFXTreeHandler.addNode(this);
|
297
|
}
|
298
|
|
299
|
|
300
|
_p = WebFXTreeAbstractNode.prototype;
|
301
|
_p._selected = false;
|
302
|
_p.indentWidth = 19;
|
303
|
_p.open = false;
|
304
|
_p.text = webFXTreeConfig.defaultText;
|
305
|
_p.action = null;
|
306
|
_p.target = null;
|
307
|
_p.toolTip = null;
|
308
|
_p._focused = false;
|
309
|
|
310
|
/* begin tree model */
|
311
|
|
312
|
_p.add = function (oChild, oBefore) {
|
313
|
var oldLast;
|
314
|
var emptyBefore = this.childNodes.length == 0;
|
315
|
var p = oChild.parentNode;
|
316
|
|
317
|
if (oBefore == null) { // append
|
318
|
if (p != null)
|
319
|
p.remove(oChild);
|
320
|
oldLast = this.getLastChild();
|
321
|
this.childNodes.push(oChild);
|
322
|
} else { // insertBefore
|
323
|
if (oBefore.parentNode != this) {
|
324
|
throw new Error("Can only add nodes before siblings");
|
325
|
}
|
326
|
if (p != null) {
|
327
|
p.remove(oChild);
|
328
|
}
|
329
|
|
330
|
arrayHelper.insertBefore(this.childNodes, oChild, oBefore);
|
331
|
}
|
332
|
|
333
|
if (oBefore) {
|
334
|
if (oBefore == this.firstChild) {
|
335
|
this.firstChild = oChild;
|
336
|
}
|
337
|
oChild.previousSibling = oBefore.previousSibling;
|
338
|
oBefore.previousSibling = oChild;
|
339
|
oChild.nextSibling = oBefore;
|
340
|
} else {
|
341
|
if (!this.firstChild) {
|
342
|
this.firstChild = oChild;
|
343
|
}
|
344
|
if (this.lastChild) {
|
345
|
this.lastChild.nextSibling = oChild;
|
346
|
}
|
347
|
oChild.previousSibling = this.lastChild;
|
348
|
this.lastChild = oChild;
|
349
|
}
|
350
|
|
351
|
oChild.parentNode = this;
|
352
|
var t = this.getTree();
|
353
|
if (t) {
|
354
|
oChild.tree = t;
|
355
|
}
|
356
|
var d = this.getDepth();
|
357
|
if (d != null) {
|
358
|
oChild.depth = d + 1;
|
359
|
}
|
360
|
|
361
|
if (this.getCreated() && !t.getSuspendRedraw()) {
|
362
|
var el = this.getChildrenElement();
|
363
|
var newEl = oChild.create();
|
364
|
var refEl = oBefore ? oBefore.getElement() : null;
|
365
|
el.insertBefore(newEl, refEl);
|
366
|
|
367
|
if (oldLast) {
|
368
|
oldLast.updateExpandIcon();
|
369
|
}
|
370
|
if (emptyBefore) {
|
371
|
this.setExpanded(this.getExpanded());
|
372
|
// if we are using classic expand will not update icon
|
373
|
if (t && t.getBehavior() != "classic")
|
374
|
this.updateIcon();
|
375
|
}
|
376
|
}
|
377
|
|
378
|
return oChild;
|
379
|
};
|
380
|
|
381
|
|
382
|
|
383
|
_p.remove = function (oChild) {
|
384
|
// backwards compatible. If no argument remove the node
|
385
|
if (arguments.length == 0) {
|
386
|
if (this.parentNode) {
|
387
|
return this.parentNode.remove(this);
|
388
|
}
|
389
|
return null;
|
390
|
}
|
391
|
|
392
|
// if we remove selected or tree with the selected we should select this
|
393
|
var t = this.getTree();
|
394
|
var si = t ? t.getSelected() : null;
|
395
|
if (si == oChild || oChild.contains(si)) {
|
396
|
if (si.getFocused()) {
|
397
|
this.select();
|
398
|
window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
|
399
|
} else {
|
400
|
this.select();
|
401
|
}
|
402
|
}
|
403
|
|
404
|
if (oChild.parentNode != this) {
|
405
|
throw new Error("Can only remove children");
|
406
|
}
|
407
|
arrayHelper.remove(this.childNodes, oChild);
|
408
|
|
409
|
if (this.lastChild == oChild) {
|
410
|
this.lastChild = oChild.previousSibling;
|
411
|
}
|
412
|
if (this.firstChild == oChild) {
|
413
|
this.firstChild = oChild.nextSibling;
|
414
|
}
|
415
|
if (oChild.previousSibling) {
|
416
|
oChild.previousSibling.nextSibling = oChild.nextSibling;
|
417
|
}
|
418
|
if (oChild.nextSibling) {
|
419
|
oChild.nextSibling.previousSibling = oChild.previousSibling;
|
420
|
}
|
421
|
|
422
|
var wasLast = oChild.isLastSibling();
|
423
|
|
424
|
oChild.parentNode = null;
|
425
|
oChild.tree = null;
|
426
|
oChild.depth = null;
|
427
|
|
428
|
if (t && this.getCreated() && !t.getSuspendRedraw()) {
|
429
|
var el = this.getChildrenElement();
|
430
|
var childEl = oChild.getElement();
|
431
|
el.removeChild(childEl);
|
432
|
if (wasLast) {
|
433
|
var newLast = this.getLastChild();
|
434
|
if (newLast) {
|
435
|
newLast.updateExpandIcon();
|
436
|
}
|
437
|
}
|
438
|
if (!this.hasChildren()) {
|
439
|
el.style.display = "none";
|
440
|
this.updateExpandIcon();
|
441
|
this.updateIcon();
|
442
|
}
|
443
|
}
|
444
|
|
445
|
return oChild;
|
446
|
};
|
447
|
|
448
|
WebFXTreeAbstractNode._onTimeoutFocus = function (sId) {
|
449
|
var jsNode = webFXTreeHandler.all[sId];
|
450
|
jsNode.focus();
|
451
|
};
|
452
|
|
453
|
_p.getId = function () {
|
454
|
return this.id;
|
455
|
};
|
456
|
|
457
|
_p.getTree = function () {
|
458
|
throw new Error("getTree called on Abstract Node");
|
459
|
};
|
460
|
|
461
|
_p.getDepth = function () {
|
462
|
throw new Error("getDepth called on Abstract Node");
|
463
|
};
|
464
|
|
465
|
_p.getCreated = function () {
|
466
|
var t = this.getTree();
|
467
|
return t && t.rendered;
|
468
|
};
|
469
|
|
470
|
_p.getParent = function () {
|
471
|
return this.parentNode;
|
472
|
};
|
473
|
|
474
|
_p.contains = function (oDescendant) {
|
475
|
if (oDescendant == null) return false;
|
476
|
if (oDescendant == this) return true;
|
477
|
var p = oDescendant.parentNode;
|
478
|
return this.contains(p);
|
479
|
};
|
480
|
|
481
|
_p.getChildren = _p.getChildNodes = function () {
|
482
|
return this.childNodes;
|
483
|
};
|
484
|
|
485
|
_p.getFirstChild = function () {
|
486
|
return this.childNodes[0];
|
487
|
};
|
488
|
|
489
|
_p.getLastChild = function () {
|
490
|
return this.childNodes[this.childNodes.length - 1];
|
491
|
};
|
492
|
|
493
|
_p.getPreviousSibling = function () {
|
494
|
return this.previousSibling;
|
495
|
//var p = this.parentNode;
|
496
|
//if (p == null) return null;
|
497
|
//var cs = p.childNodes;
|
498
|
//return cs[arrayHelper.indexOf(cs, this) - 1]
|
499
|
};
|
500
|
|
501
|
_p.getNextSibling = function () {
|
502
|
return this.nextSibling;
|
503
|
//var p = this.parentNode;
|
504
|
//if (p == null) return null;
|
505
|
//var cs = p.childNodes;
|
506
|
//return cs[arrayHelper.indexOf(cs, this) + 1]
|
507
|
};
|
508
|
|
509
|
_p.hasChildren = function () {
|
510
|
return this.childNodes.length > 0;
|
511
|
};
|
512
|
|
513
|
_p.isLastSibling = function () {
|
514
|
return this.nextSibling == null;
|
515
|
//return this.parentNode && this == this.parentNode.getLastChild();
|
516
|
};
|
517
|
|
518
|
_p.findChildByText = function (s, n) {
|
519
|
if (!n) {
|
520
|
n = 0;
|
521
|
}
|
522
|
var isRe = s instanceof RegExp;
|
523
|
for (var i = 0; i < this.childNodes.length; i++) {
|
524
|
if (isRe && s.test(this.childNodes[i].getText()) ||
|
525
|
this.childNodes[i].getText() == s) {
|
526
|
if (n == 0) {
|
527
|
return this.childNodes[i];
|
528
|
}
|
529
|
n--;
|
530
|
}
|
531
|
}
|
532
|
return null;
|
533
|
};
|
534
|
|
535
|
_p.findNodeByText = function (s, n) {
|
536
|
if (!n) {
|
537
|
n = 0;
|
538
|
}
|
539
|
var isRe = s instanceof RegExp;
|
540
|
if (isRe && s.test(this.getText()) || this.getText() == s) {
|
541
|
if (n == 0) {
|
542
|
return this.childNodes[i];
|
543
|
}
|
544
|
n--;
|
545
|
}
|
546
|
|
547
|
var res;
|
548
|
for (var i = 0; i < this.childNodes.length; i++) {
|
549
|
res = this.childNodes[i].findNodeByText(s, n);
|
550
|
if (res) {
|
551
|
return res;
|
552
|
}
|
553
|
}
|
554
|
return null;
|
555
|
};
|
556
|
|
557
|
/* end tree model */
|
558
|
|
559
|
_p.setId = function (sId) {
|
560
|
var el = this.getElement();
|
561
|
webFXTreeHandler.removeNode(this);
|
562
|
this.id = sId;
|
563
|
if (el) {
|
564
|
el.id = sId;
|
565
|
}
|
566
|
webFXTreeHandler.addNode(this);
|
567
|
};
|
568
|
|
569
|
_p.isSelected = function () {
|
570
|
return this._selected;
|
571
|
};
|
572
|
|
573
|
_p.select = function () {
|
574
|
this._setSelected(true);
|
575
|
};
|
576
|
|
577
|
_p.deselect = function () {
|
578
|
this._setSelected(false);
|
579
|
};
|
580
|
|
581
|
_p._setSelected = function (b) {
|
582
|
var t = this.getTree();
|
583
|
if (!t) return;
|
584
|
if (this._selected != b) {
|
585
|
this._selected = b;
|
586
|
|
587
|
var wasFocused = false; // used to keep focus state
|
588
|
var si = t.getSelected();
|
589
|
if (b && si != null && si != this) {
|
590
|
var oldFireChange = t._fireChange;
|
591
|
wasFocused = si._focused;
|
592
|
t._fireChange = false;
|
593
|
si._setSelected(false);
|
594
|
t._fireChange = oldFireChange;
|
595
|
}
|
596
|
|
597
|
var el = this.getRowElement();
|
598
|
if (el) {
|
599
|
el.className = this.getRowClassName();
|
600
|
}
|
601
|
if (b) {
|
602
|
this._setTabIndex(t.tabIndex);
|
603
|
t._selectedItem = this;
|
604
|
t._fireOnChange();
|
605
|
t.setSelected(this);
|
606
|
if (wasFocused) {
|
607
|
this.focus();
|
608
|
}
|
609
|
} else {
|
610
|
this._setTabIndex(-1);
|
611
|
}
|
612
|
|
613
|
if (t.getBehavior() != "classic") {
|
614
|
this.updateIcon();
|
615
|
}
|
616
|
}
|
617
|
};
|
618
|
|
619
|
|
620
|
_p.getExpanded = function () {
|
621
|
return this.open;
|
622
|
};
|
623
|
|
624
|
_p.setExpanded = function (b) {
|
625
|
var ce;
|
626
|
this.open = b;
|
627
|
var t = this.getTree();
|
628
|
if (this.hasChildren()) {
|
629
|
var si = t ? t.getSelected() : null;
|
630
|
if (!b && this.contains(si)) {
|
631
|
this.select();
|
632
|
}
|
633
|
|
634
|
var el = this.getElement();
|
635
|
if (el) {
|
636
|
ce = this.getChildrenElement();
|
637
|
if (ce) {
|
638
|
ce.style.display = b ? "block" : "none";
|
639
|
}
|
640
|
var eie = this.getExpandIconElement();
|
641
|
if (eie) {
|
642
|
eie.src = this.getExpandIconSrc();
|
643
|
}
|
644
|
}
|
645
|
|
646
|
if (webFXTreeConfig.usePersistence) {
|
647
|
webFXTreeHandler.persistenceManager.setExpanded(this, b);
|
648
|
}
|
649
|
} else {
|
650
|
ce = this.getChildrenElement();
|
651
|
if (ce)
|
652
|
ce.style.display = "none";
|
653
|
}
|
654
|
if (t && t.getBehavior() == "classic") {
|
655
|
this.updateIcon();
|
656
|
}
|
657
|
};
|
658
|
|
659
|
_p.toggle = function () {
|
660
|
this.setExpanded(!this.getExpanded());
|
661
|
};
|
662
|
|
663
|
_p.expand = function () {
|
664
|
this.setExpanded(true);
|
665
|
};
|
666
|
|
667
|
_p.collapse = function () {
|
668
|
this.setExpanded(false);
|
669
|
};
|
670
|
|
671
|
_p.collapseChildren = function () {
|
672
|
var cs = this.childNodes;
|
673
|
for (var i = 0; i < cs.length; i++) {
|
674
|
cs[i].collapseAll();
|
675
|
}
|
676
|
};
|
677
|
|
678
|
_p.collapseAll = function () {
|
679
|
this.collapseChildren();
|
680
|
this.collapse();
|
681
|
};
|
682
|
|
683
|
_p.expandChildren = function () {
|
684
|
var cs = this.childNodes;
|
685
|
for (var i = 0; i < cs.length; i++) {
|
686
|
cs[i].expandAll();
|
687
|
}
|
688
|
};
|
689
|
|
690
|
_p.expandAll = function () {
|
691
|
this.expandChildren();
|
692
|
this.expand();
|
693
|
};
|
694
|
|
695
|
_p.reveal = function () {
|
696
|
var p = this.getParent();
|
697
|
if (p) {
|
698
|
p.setExpanded(true);
|
699
|
p.reveal();
|
700
|
}
|
701
|
};
|
702
|
|
703
|
_p.openPath = function (sPath, bSelect, bFocus) {
|
704
|
if (sPath == "") {
|
705
|
if (bSelect) {
|
706
|
this.select();
|
707
|
}
|
708
|
if (bFocus) {
|
709
|
window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
|
710
|
}
|
711
|
return;
|
712
|
}
|
713
|
|
714
|
var parts = sPath.split("/");
|
715
|
var remainingPath = parts.slice(1).join("/");
|
716
|
var t = this.getTree();
|
717
|
if (sPath.charAt(0) == "/") {
|
718
|
if (t) {
|
719
|
t.openPath(remainingPath, bSelect, bFocus);
|
720
|
} else {
|
721
|
throw "Invalid path";
|
722
|
}
|
723
|
} else {
|
724
|
// open
|
725
|
this.setExpanded(true);
|
726
|
parts = sPath.split("/");
|
727
|
var ti = this.findChildByText(parts[0]);
|
728
|
if (!ti) {
|
729
|
throw "Could not find child node with text \"" + parts[0] + "\"";
|
730
|
}
|
731
|
ti.openPath(remainingPath, bSelect, bFocus);
|
732
|
}
|
733
|
};
|
734
|
|
735
|
_p.focus = function () {
|
736
|
var el = this.getLabelElement();
|
737
|
if (el) {
|
738
|
el.focus();
|
739
|
}
|
740
|
};
|
741
|
|
742
|
_p.getFocused = function () {
|
743
|
return this._focused;
|
744
|
};
|
745
|
|
746
|
_p._setTabIndex = function (i) {
|
747
|
var a = this.getLabelElement();
|
748
|
if (a) {
|
749
|
a.setAttribute("tabindex", i);
|
750
|
}
|
751
|
};
|
752
|
|
753
|
|
754
|
// HTML generation
|
755
|
|
756
|
_p.toHtml = function () {
|
757
|
var sb = [];
|
758
|
var cs = this.childNodes;
|
759
|
var l = cs.length;
|
760
|
for (var y = 0; y < l; y++) {
|
761
|
sb[y] = cs[y].toHtml();
|
762
|
}
|
763
|
|
764
|
var t = this.getTree();
|
765
|
var hideLines = !t.getShowLines() || t == this.parentNode && !t.getShowRootLines();
|
766
|
|
767
|
var childrenHtml = "<div class=\"webfx-tree-children" +
|
768
|
(hideLines ? "-nolines" : "") + "\" style=\"" +
|
769
|
this.getLineStyle() +
|
770
|
(this.getExpanded() && this.hasChildren() ? "" : "display:none;") +
|
771
|
"\">" +
|
772
|
sb.join("") +
|
773
|
"</div>";
|
774
|
|
775
|
return "<div class=\"webfx-tree-item\" id=\"" +
|
776
|
this.id + "\"" + this.getEventHandlersHtml() + ">" +
|
777
|
this.getRowHtml() +
|
778
|
childrenHtml +
|
779
|
"</div>";
|
780
|
};
|
781
|
|
782
|
_p.getRowHtml = function () {
|
783
|
var t = this.getTree();
|
784
|
return "<div class=\"" + this.getRowClassName() + "\" style=\"padding-left:" +
|
785
|
Math.max(0, (this.getDepth() - 1) * this.indentWidth) + "px\">" +
|
786
|
this.getExpandIconHtml() +
|
787
|
//"<span class=\"webfx-tree-icon-and-label\">" +
|
788
|
this.getIconHtml() +
|
789
|
this.getLabelHtml() +
|
790
|
//"</span>" +
|
791
|
"</div>";
|
792
|
};
|
793
|
|
794
|
_p.getRowClassName = function () {
|
795
|
return "webfx-tree-row" + (this.isSelected() ? " selected" : "") +
|
796
|
(this.action ? "" : " no-action");
|
797
|
};
|
798
|
|
799
|
_p.getLabelHtml = function () {
|
800
|
var toolTip = this.getToolTip();
|
801
|
var target = this.getTarget();
|
802
|
return "<a href=\"" + webFXTreeHandler.textToHtml(this._getHref()) +
|
803
|
"\" class=\"webfx-tree-item-label\" tabindex=\"-1\"" +
|
804
|
(toolTip ? " title=\"" + webFXTreeHandler.textToHtml(toolTip) + "\"" : "") +
|
805
|
(target ? " target=\"" + target + "\"" : "") +
|
806
|
" onfocus=\"webFXTreeHandler.handleEvent(event)\"" +
|
807
|
" onblur=\"webFXTreeHandler.handleEvent(event)\">" +
|
808
|
this.getHtml() + "</a>";
|
809
|
};
|
810
|
|
811
|
_p._getHref = function () {
|
812
|
if (typeof this.action == "string")
|
813
|
return this.action;
|
814
|
else
|
815
|
return "#";
|
816
|
};
|
817
|
|
818
|
_p.getEventHandlersHtml = function () {
|
819
|
return "";
|
820
|
};
|
821
|
|
822
|
_p.getIconHtml = function () {
|
823
|
// here we are not using textToHtml since the file names rarerly contains
|
824
|
// HTML...
|
825
|
return "<img class=\"webfx-tree-icon\" src=\"" + this.getIconSrc() + "\">";
|
826
|
};
|
827
|
|
828
|
_p.getIconSrc = function () {
|
829
|
throw new Error("getIconSrc called on Abstract Node");
|
830
|
};
|
831
|
|
832
|
_p.getExpandIconHtml = function () {
|
833
|
// here we are not using textToHtml since the file names rarerly contains
|
834
|
// HTML...
|
835
|
return "<img class=\"webfx-tree-expand-icon\" src=\"" +
|
836
|
this.getExpandIconSrc() + "\">";
|
837
|
};
|
838
|
|
839
|
|
840
|
_p.getExpandIconSrc = function () {
|
841
|
var src;
|
842
|
var t = this.getTree();
|
843
|
var hideLines = !t.getShowLines() || t == this.parentNode && !t.getShowRootLines();
|
844
|
|
845
|
if (this.hasChildren()) {
|
846
|
var bits = 0;
|
847
|
/*
|
848
|
Bitmap used to determine which icon to use
|
849
|
1 Plus
|
850
|
2 Minus
|
851
|
4 T Line
|
852
|
8 L Line
|
853
|
*/
|
854
|
|
855
|
if (t && t.getShowExpandIcons()) {
|
856
|
if (this.getExpanded()) {
|
857
|
bits = 2;
|
858
|
} else {
|
859
|
bits = 1;
|
860
|
}
|
861
|
}
|
862
|
|
863
|
if (t && !hideLines) {
|
864
|
if (this.isLastSibling()) {
|
865
|
bits += 4;
|
866
|
} else {
|
867
|
bits += 8;
|
868
|
}
|
869
|
}
|
870
|
|
871
|
switch (bits) {
|
872
|
case 1:
|
873
|
return webFXTreeConfig.plusIcon;
|
874
|
case 2:
|
875
|
return webFXTreeConfig.minusIcon;
|
876
|
case 4:
|
877
|
return webFXTreeConfig.lIcon;
|
878
|
case 5:
|
879
|
return webFXTreeConfig.lPlusIcon;
|
880
|
case 6:
|
881
|
return webFXTreeConfig.lMinusIcon;
|
882
|
case 8:
|
883
|
return webFXTreeConfig.tIcon;
|
884
|
case 9:
|
885
|
return webFXTreeConfig.tPlusIcon;
|
886
|
case 10:
|
887
|
return webFXTreeConfig.tMinusIcon;
|
888
|
default: // 0
|
889
|
return webFXTreeConfig.blankIcon;
|
890
|
}
|
891
|
} else {
|
892
|
if (t && hideLines) {
|
893
|
return webFXTreeConfig.blankIcon;
|
894
|
} else if (this.isLastSibling()) {
|
895
|
return webFXTreeConfig.lIcon;
|
896
|
} else {
|
897
|
return webFXTreeConfig.tIcon;
|
898
|
}
|
899
|
}
|
900
|
};
|
901
|
|
902
|
_p.getLineStyle = function () {
|
903
|
return "background-position:" + this.getLineStyle2() + ";";
|
904
|
};
|
905
|
|
906
|
_p.getLineStyle2 = function () {
|
907
|
return (this.isLastSibling() ? "-100" : (this.getDepth() - 1) * this.indentWidth) + "px 0";
|
908
|
};
|
909
|
|
910
|
// End HTML generation
|
911
|
|
912
|
// DOM
|
913
|
// this returns the div for the tree node
|
914
|
_p.getElement = function () {
|
915
|
return document.getElementById(this.id);
|
916
|
};
|
917
|
|
918
|
// the row is the div that is used to draw the node without the children
|
919
|
_p.getRowElement = function () {
|
920
|
var el = this.getElement();
|
921
|
if (!el) return null;
|
922
|
return el.firstChild;
|
923
|
};
|
924
|
|
925
|
// plus/minus image
|
926
|
_p.getExpandIconElement = function () {
|
927
|
var el = this.getRowElement();
|
928
|
if (!el) return null;
|
929
|
return el.firstChild;
|
930
|
};
|
931
|
|
932
|
_p.getIconElement = function () {
|
933
|
var el = this.getRowElement();
|
934
|
if (!el) return null;
|
935
|
return el.childNodes[1];
|
936
|
};
|
937
|
|
938
|
// anchor element
|
939
|
_p.getLabelElement = function () {
|
940
|
var el = this.getRowElement();
|
941
|
if (!el) return null;
|
942
|
return el.lastChild;
|
943
|
};
|
944
|
|
945
|
// the div containing the children
|
946
|
_p.getChildrenElement = function () {
|
947
|
var el = this.getElement();
|
948
|
if (!el) return null;
|
949
|
return el.lastChild;
|
950
|
};
|
951
|
|
952
|
|
953
|
// IE uses about:blank if not attached to document and this can cause Win2k3
|
954
|
// to fail
|
955
|
if (webFXTreeHandler.ie) {
|
956
|
_p.create = function () {
|
957
|
var dummy = document.createElement("div");
|
958
|
dummy.style.display = "none";
|
959
|
document.body.appendChild(dummy);
|
960
|
dummy.innerHTML = this.toHtml();
|
961
|
var res = dummy.removeChild(dummy.firstChild);
|
962
|
document.body.removeChild(dummy);
|
963
|
return res;
|
964
|
};
|
965
|
} else {
|
966
|
_p.create = function () {
|
967
|
var dummy = document.createElement("div");
|
968
|
dummy.innerHTML = this.toHtml();
|
969
|
return dummy.removeChild(dummy.firstChild);
|
970
|
};
|
971
|
}
|
972
|
|
973
|
// Getters and setters for some common fields
|
974
|
|
975
|
_p.setIcon = function (s) {
|
976
|
this.icon = s;
|
977
|
if (this.getCreated()) {
|
978
|
this.updateIcon();
|
979
|
}
|
980
|
};
|
981
|
|
982
|
_p.getIcon = function () {
|
983
|
return this.icon;
|
984
|
};
|
985
|
|
986
|
_p.setOpenIcon = function (s) {
|
987
|
this.openIcon = s;
|
988
|
if (this.getCreated()) {
|
989
|
this.updateIcon();
|
990
|
}
|
991
|
};
|
992
|
|
993
|
_p.getOpenIcon = function () {
|
994
|
return this.openIcon;
|
995
|
};
|
996
|
|
997
|
_p.setText = function (s) {
|
998
|
this.setHtml(webFXTreeHandler.textToHtml(s));
|
999
|
};
|
1000
|
|
1001
|
_p.getText = function () {
|
1002
|
return webFXTreeHandler.htmlToText(this.getHtml());
|
1003
|
};
|
1004
|
|
1005
|
_p.setHtml = function (s) {
|
1006
|
this.text = s;
|
1007
|
var el = this.getLabelElement();
|
1008
|
if (el) {
|
1009
|
el.innerHTML = s;
|
1010
|
}
|
1011
|
};
|
1012
|
|
1013
|
_p.getHtml = function () {
|
1014
|
return this.text;
|
1015
|
};
|
1016
|
|
1017
|
_p.setTarget = function (s) {
|
1018
|
this.target = s;
|
1019
|
};
|
1020
|
|
1021
|
_p.getTarget = function () {
|
1022
|
return this.target;
|
1023
|
};
|
1024
|
|
1025
|
_p.setToolTip = function (s) {
|
1026
|
this.toolTip = s;
|
1027
|
var el = this.getLabelElement();
|
1028
|
if (el) {
|
1029
|
el.title = s;
|
1030
|
}
|
1031
|
};
|
1032
|
|
1033
|
_p.getToolTip = function () {
|
1034
|
return this.toolTip;
|
1035
|
};
|
1036
|
|
1037
|
_p.setAction = function (oAction) {
|
1038
|
this.action = oAction;
|
1039
|
var el = this.getLabelElement();
|
1040
|
if (el) {
|
1041
|
el.href = this._getHref();
|
1042
|
}
|
1043
|
el = this.getRowElement();
|
1044
|
if (el) {
|
1045
|
el.className = this.getRowClassName();
|
1046
|
}
|
1047
|
};
|
1048
|
|
1049
|
_p.getAction = function () {
|
1050
|
return this.action;
|
1051
|
};
|
1052
|
|
1053
|
// update methods
|
1054
|
|
1055
|
_p.update = function () {
|
1056
|
var t = this.getTree();
|
1057
|
if (t.suspendRedraw) return;
|
1058
|
var el = this.getElement();
|
1059
|
if (!el || !el.parentNode) return;
|
1060
|
var newEl = this.create();
|
1061
|
el.parentNode.replaceChild(newEl, el);
|
1062
|
this._setTabIndex(this.tabIndex); // in case root had the tab index
|
1063
|
var si = t.getSelected();
|
1064
|
if (si && si.getFocused()) {
|
1065
|
si.focus();
|
1066
|
}
|
1067
|
};
|
1068
|
|
1069
|
_p.updateExpandIcon = function () {
|
1070
|
var t = this.getTree();
|
1071
|
if (t.suspendRedraw) return;
|
1072
|
var img = this.getExpandIconElement();
|
1073
|
img.src = this.getExpandIconSrc();
|
1074
|
var cel = this.getChildrenElement();
|
1075
|
cel.style.backgroundPosition = this.getLineStyle2();
|
1076
|
};
|
1077
|
|
1078
|
_p.updateIcon = function () {
|
1079
|
var t = this.getTree();
|
1080
|
if (t.suspendRedraw) return;
|
1081
|
var img = this.getIconElement();
|
1082
|
img.src = this.getIconSrc();
|
1083
|
};
|
1084
|
|
1085
|
// End DOM
|
1086
|
|
1087
|
_p._callSuspended = function (f) {
|
1088
|
var t = this.getTree();
|
1089
|
var sr = t.getSuspendRedraw();
|
1090
|
t.setSuspendRedraw(true);
|
1091
|
f.call(this);
|
1092
|
t.setSuspendRedraw(sr);
|
1093
|
};
|
1094
|
|
1095
|
// Event handlers
|
1096
|
|
1097
|
_p._onmousedown = function (e) {
|
1098
|
var el = e.target || e.srcElement;
|
1099
|
// expand icon
|
1100
|
if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren()) {
|
1101
|
this.toggle();
|
1102
|
if (webFXTreeHandler.ie) {
|
1103
|
window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
|
1104
|
}
|
1105
|
return false;
|
1106
|
}
|
1107
|
|
1108
|
this.select();
|
1109
|
if (/*!/webfx-tree-item-label/.test(el.className) && */!webFXTreeHandler.opera) { // opera cancels the click if focus is called
|
1110
|
|
1111
|
// in case we are not clicking on the label
|
1112
|
if (webFXTreeHandler.ie) {
|
1113
|
window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
|
1114
|
} else {
|
1115
|
this.focus();
|
1116
|
}
|
1117
|
}
|
1118
|
var rowEl = this.getRowElement();
|
1119
|
if (rowEl) {
|
1120
|
rowEl.className = this.getRowClassName();
|
1121
|
}
|
1122
|
|
1123
|
return false;
|
1124
|
};
|
1125
|
|
1126
|
_p._onclick = function (e) {
|
1127
|
var el = e.target || e.srcElement;
|
1128
|
// expand icon
|
1129
|
if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren()) {
|
1130
|
return false;
|
1131
|
}
|
1132
|
|
1133
|
if (typeof this.action == "function") {
|
1134
|
this.action();
|
1135
|
} else if (this.action != null) {
|
1136
|
window.open(this.action, this.target || "_self");
|
1137
|
}
|
1138
|
return false;
|
1139
|
};
|
1140
|
|
1141
|
|
1142
|
_p._ondblclick = function (e) {
|
1143
|
var el = e.target || e.srcElement;
|
1144
|
// expand icon
|
1145
|
if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren()) {
|
1146
|
return;
|
1147
|
}
|
1148
|
|
1149
|
this.toggle();
|
1150
|
};
|
1151
|
|
1152
|
_p._onfocus = function (e) {
|
1153
|
this.select();
|
1154
|
this._focused = true;
|
1155
|
};
|
1156
|
|
1157
|
_p._onblur = function (e) {
|
1158
|
this._focused = false;
|
1159
|
};
|
1160
|
|
1161
|
_p._onkeydown = function (e) {
|
1162
|
var n;
|
1163
|
var rv = true;
|
1164
|
switch (e.keyCode) {
|
1165
|
case 39: // RIGHT
|
1166
|
if (e.altKey) {
|
1167
|
rv = true;
|
1168
|
break;
|
1169
|
}
|
1170
|
if (this.hasChildren()) {
|
1171
|
if (!this.getExpanded()) {
|
1172
|
this.setExpanded(true);
|
1173
|
} else {
|
1174
|
this.getFirstChild().focus();
|
1175
|
}
|
1176
|
}
|
1177
|
rv = false;
|
1178
|
break;
|
1179
|
case 37: // LEFT
|
1180
|
if (e.altKey) {
|
1181
|
rv = true;
|
1182
|
break;
|
1183
|
}
|
1184
|
if (this.hasChildren() && this.getExpanded()) {
|
1185
|
this.setExpanded(false);
|
1186
|
} else {
|
1187
|
var p = this.getParent();
|
1188
|
var t = this.getTree();
|
1189
|
// don't go to root if hidden
|
1190
|
if (p && (t.showRootNode || p != t)) {
|
1191
|
p.focus();
|
1192
|
}
|
1193
|
}
|
1194
|
rv = false;
|
1195
|
break;
|
1196
|
|
1197
|
case 40: // DOWN
|
1198
|
n = this.getNextShownNode();
|
1199
|
if (n) {
|
1200
|
n.focus();
|
1201
|
}
|
1202
|
rv = false;
|
1203
|
break;
|
1204
|
case 38: // UP
|
1205
|
n = this.getPreviousShownNode()
|
1206
|
if (n) {
|
1207
|
n.focus();
|
1208
|
}
|
1209
|
rv = false;
|
1210
|
break;
|
1211
|
}
|
1212
|
|
1213
|
if (!rv && e.preventDefault) {
|
1214
|
e.preventDefault();
|
1215
|
}
|
1216
|
e.returnValue = rv;
|
1217
|
return rv;
|
1218
|
};
|
1219
|
|
1220
|
_p._onkeypress = function (e) {
|
1221
|
if (!e.altKey && e.keyCode >= 37 && e.keyCode <= 40) {
|
1222
|
if (e.preventDefault) {
|
1223
|
e.preventDefault();
|
1224
|
}
|
1225
|
e.returnValue = false;
|
1226
|
return false;
|
1227
|
}
|
1228
|
};
|
1229
|
|
1230
|
// End event handlers
|
1231
|
|
1232
|
_p.dispose = function () {
|
1233
|
if (this.disposed) return;
|
1234
|
for (var i = this.childNodes.length - 1; i >= 0; i--) {
|
1235
|
this.childNodes[i].dispose();
|
1236
|
}
|
1237
|
this.tree = null;
|
1238
|
this.parentNode = null;
|
1239
|
this.childNodes = null;
|
1240
|
this.disposed = true;
|
1241
|
};
|
1242
|
|
1243
|
// Some methods that are usable when navigating the tree using the arrows
|
1244
|
_p.getLastShownDescendant = function () {
|
1245
|
if (!this.getExpanded() || !this.hasChildren()) {
|
1246
|
return this;
|
1247
|
}
|
1248
|
// we know there is at least 1 child
|
1249
|
return this.getLastChild().getLastShownDescendant();
|
1250
|
};
|
1251
|
|
1252
|
_p.getNextShownNode = function () {
|
1253
|
if (this.hasChildren() && this.getExpanded()) {
|
1254
|
return this.getFirstChild();
|
1255
|
} else {
|
1256
|
var p = this;
|
1257
|
var next;
|
1258
|
while (p != null) {
|
1259
|
next = p.getNextSibling();
|
1260
|
if (next != null) {
|
1261
|
return next;
|
1262
|
}
|
1263
|
p = p.getParent();
|
1264
|
}
|
1265
|
return null;
|
1266
|
}
|
1267
|
};
|
1268
|
|
1269
|
_p.getPreviousShownNode = function () {
|
1270
|
var ps = this.getPreviousSibling();
|
1271
|
if (ps != null) {
|
1272
|
return ps.getLastShownDescendant();
|
1273
|
}
|
1274
|
var p = this.getParent();
|
1275
|
var t = this.getTree();
|
1276
|
if (!t.showRootNode && p == t) {
|
1277
|
return null;
|
1278
|
}
|
1279
|
return p;
|
1280
|
};
|
1281
|
|
1282
|
|
1283
|
|
1284
|
|
1285
|
|
1286
|
|
1287
|
|
1288
|
///////////////////////////////////////////////////////////////////////////////
|
1289
|
// WebFXTree
|
1290
|
///////////////////////////////////////////////////////////////////////////////
|
1291
|
|
1292
|
function WebFXTree(sText, oAction, sBehavior, sIcon, sOpenIcon) {
|
1293
|
WebFXTreeAbstractNode.call(this, sText, oAction);
|
1294
|
if (sIcon) this.icon = sIcon;
|
1295
|
if (sOpenIcon) this.openIcon = sOpenIcon;
|
1296
|
if (sBehavior) this.behavior = sBehavior;
|
1297
|
}
|
1298
|
|
1299
|
_p = WebFXTree.prototype = new WebFXTreeAbstractNode;
|
1300
|
_p.indentWidth = 19;
|
1301
|
_p.open = true;
|
1302
|
_p._selectedItem = null;
|
1303
|
_p._fireChange = true;
|
1304
|
_p.rendered = false;
|
1305
|
_p.suspendRedraw = false;
|
1306
|
_p.showLines = true;
|
1307
|
_p.showExpandIcons = true;
|
1308
|
_p.showRootNode = true;
|
1309
|
_p.showRootLines = true;
|
1310
|
|
1311
|
_p.getTree = function () {
|
1312
|
return this;
|
1313
|
};
|
1314
|
|
1315
|
_p.getDepth = function () {
|
1316
|
return 0;
|
1317
|
};
|
1318
|
|
1319
|
_p.getCreated = function () {
|
1320
|
return this.rendered;
|
1321
|
};
|
1322
|
|
1323
|
|
1324
|
/* end tree model */
|
1325
|
|
1326
|
_p.getExpanded = function () {
|
1327
|
return !this.showRootNode || WebFXTreeAbstractNode.prototype.getExpanded.call(this);
|
1328
|
};
|
1329
|
|
1330
|
_p.setExpanded = function (b) {
|
1331
|
if (!this.showRootNode) {
|
1332
|
this.open = b;
|
1333
|
} else {
|
1334
|
WebFXTreeAbstractNode.prototype.setExpanded.call(this, b);
|
1335
|
}
|
1336
|
};
|
1337
|
|
1338
|
_p.getExpandIconHtml = function () {
|
1339
|
return "";
|
1340
|
};
|
1341
|
|
1342
|
// we don't have an expand icon here
|
1343
|
_p.getIconElement = function () {
|
1344
|
var el = this.getRowElement();
|
1345
|
if (!el) return null;
|
1346
|
return el.firstChild;
|
1347
|
};
|
1348
|
|
1349
|
// no expand icon for root element
|
1350
|
_p.getExpandIconElement = function (oDoc) {
|
1351
|
return null;
|
1352
|
};
|
1353
|
|
1354
|
_p.updateExpandIcon = function () {
|
1355
|
// no expand icon
|
1356
|
};
|
1357
|
|
1358
|
_p.getRowClassName = function () {
|
1359
|
return WebFXTreeAbstractNode.prototype.getRowClassName.call(this) +
|
1360
|
(this.showRootNode ? "" : " webfx-tree-hide-root");
|
1361
|
};
|
1362
|
|
1363
|
|
1364
|
// if classic then the openIcon is used for expanded, otherwise openIcon is used
|
1365
|
// for selected
|
1366
|
|
1367
|
_p.getIconSrc = function () {
|
1368
|
var behavior = this.getTree() ? this.getTree().getBehavior() : webFXTreeConfig.defaultBehavior;
|
1369
|
var open = behavior == "classic" && this.getExpanded() ||
|
1370
|
behavior != "classic" && this.isSelected();
|
1371
|
if (open && this.openIcon) {
|
1372
|
return this.openIcon;
|
1373
|
}
|
1374
|
if (!open && this.icon) {
|
1375
|
return this.icon;
|
1376
|
}
|
1377
|
// fall back on default icons
|
1378
|
return open ? webFXTreeConfig.openRootIcon : webFXTreeConfig.rootIcon;
|
1379
|
};
|
1380
|
|
1381
|
_p.getEventHandlersHtml = function () {
|
1382
|
return " onclick=\"return webFXTreeHandler.handleEvent(event)\" " +
|
1383
|
"onmousedown=\"return webFXTreeHandler.handleEvent(event)\" " +
|
1384
|
"ondblclick=\"return webFXTreeHandler.handleEvent(event)\" " +
|
1385
|
"onkeydown=\"return webFXTreeHandler.handleEvent(event)\" " +
|
1386
|
"onkeypress=\"return webFXTreeHandler.handleEvent(event)\"";
|
1387
|
};
|
1388
|
|
1389
|
_p.setSelected = function (o) {
|
1390
|
if (this._selectedItem != o && o) {
|
1391
|
o._setSelected(true);
|
1392
|
}
|
1393
|
};
|
1394
|
|
1395
|
_p._fireOnChange = function () {
|
1396
|
if (this._fireChange && typeof this.onchange == "function") {
|
1397
|
this.onchange();
|
1398
|
}
|
1399
|
};
|
1400
|
|
1401
|
_p.getSelected = function () {
|
1402
|
return this._selectedItem;
|
1403
|
};
|
1404
|
|
1405
|
_p.tabIndex = "";
|
1406
|
|
1407
|
_p.setTabIndex = function (i) {
|
1408
|
var n = this._selectedItem || (this.showRootNode ? this : this.firstChild);
|
1409
|
this.tabIndex = i;
|
1410
|
if (n) {
|
1411
|
n._setTabIndex(i);
|
1412
|
}
|
1413
|
};
|
1414
|
|
1415
|
_p.getTabIndex = function () {
|
1416
|
return this.tabIndex;
|
1417
|
};
|
1418
|
|
1419
|
_p.setBehavior = function (s) {
|
1420
|
this.behavior = s;
|
1421
|
};
|
1422
|
|
1423
|
_p.getBehavior = function () {
|
1424
|
return this.behavior || webFXTreeConfig.defaultBehavior;
|
1425
|
};
|
1426
|
|
1427
|
_p.setShowLines = function (b) {
|
1428
|
if (this.showLines != b) {
|
1429
|
this.showLines = b;
|
1430
|
if (this.rendered) {
|
1431
|
this.update();
|
1432
|
}
|
1433
|
}
|
1434
|
};
|
1435
|
|
1436
|
_p.getShowLines = function () {
|
1437
|
return this.showLines;
|
1438
|
};
|
1439
|
|
1440
|
_p.setShowRootLines = function (b) {
|
1441
|
if (this.showRootLines != b) {
|
1442
|
this.showRootLines = b;
|
1443
|
if (this.rendered) {
|
1444
|
this.update();
|
1445
|
}
|
1446
|
}
|
1447
|
};
|
1448
|
|
1449
|
_p.getShowRootLines = function () {
|
1450
|
return this.showRootLines;
|
1451
|
};
|
1452
|
|
1453
|
_p.setShowExpandIcons = function (b) {
|
1454
|
if (this.showExpandIcons != b) {
|
1455
|
this.showExpandIcons = b;
|
1456
|
if (this.rendered) {
|
1457
|
this.getTree().update();
|
1458
|
}
|
1459
|
}
|
1460
|
};
|
1461
|
|
1462
|
_p.getShowExpandIcons = function () {
|
1463
|
return this.showExpandIcons;
|
1464
|
};
|
1465
|
|
1466
|
_p.setShowRootNode = function (b) {
|
1467
|
if (this.showRootNode != b) {
|
1468
|
this.showRootNode = b;
|
1469
|
if (this.rendered) {
|
1470
|
this.getTree().update();
|
1471
|
}
|
1472
|
}
|
1473
|
};
|
1474
|
|
1475
|
_p.getShowRoootNode = function () {
|
1476
|
return this.showRootNode;
|
1477
|
};
|
1478
|
|
1479
|
_p.onchange = function () {};
|
1480
|
|
1481
|
_p.create = function () {
|
1482
|
var el = WebFXTreeAbstractNode.prototype.create.call(this);
|
1483
|
this.setTabIndex(this.tabIndex);
|
1484
|
this.rendered = true;
|
1485
|
return el;
|
1486
|
};
|
1487
|
|
1488
|
_p.write = function () {
|
1489
|
document.write(this.toHtml());
|
1490
|
this.setTabIndex(this.tabIndex);
|
1491
|
this.rendered = true;
|
1492
|
};
|
1493
|
|
1494
|
_p.setSuspendRedraw = function (b) {
|
1495
|
this.suspendRedraw = b;
|
1496
|
};
|
1497
|
|
1498
|
_p.getSuspendRedraw = function () {
|
1499
|
return this.suspendRedraw;
|
1500
|
};
|
1501
|
|
1502
|
|
1503
|
|
1504
|
///////////////////////////////////////////////////////////////////////////////
|
1505
|
// WebFXTreeItem
|
1506
|
///////////////////////////////////////////////////////////////////////////////
|
1507
|
|
1508
|
function WebFXTreeItem(sText, oAction, eParent, sIcon, sOpenIcon) {
|
1509
|
WebFXTreeAbstractNode.call(this, sText, oAction);
|
1510
|
if (sIcon) this.icon = sIcon;
|
1511
|
if (sOpenIcon) this.openIcon = sOpenIcon;
|
1512
|
if (eParent) eParent.add(this);
|
1513
|
}
|
1514
|
|
1515
|
_p = WebFXTreeItem.prototype = new WebFXTreeAbstractNode;
|
1516
|
_p.tree = null;
|
1517
|
|
1518
|
/* tree model */
|
1519
|
|
1520
|
_p.getDepth = function () {
|
1521
|
if (this.depth != null) {
|
1522
|
return this.depth;
|
1523
|
}
|
1524
|
if (this.parentNode) {
|
1525
|
var pd = this.parentNode.getDepth();
|
1526
|
return this.depth = (pd != null ? pd + 1 : null);
|
1527
|
}
|
1528
|
return null;
|
1529
|
};
|
1530
|
|
1531
|
_p.getTree = function () {
|
1532
|
if (this.tree) {
|
1533
|
return this.tree;
|
1534
|
}
|
1535
|
if (this.parentNode) {
|
1536
|
return this.tree = this.parentNode.getTree();
|
1537
|
}
|
1538
|
return null;
|
1539
|
};
|
1540
|
|
1541
|
_p.getCreated = function () {
|
1542
|
var t = this.getTree();
|
1543
|
return t && t.getCreated();
|
1544
|
};
|
1545
|
|
1546
|
// if classic then the openIcon is used for expanded, otherwise openIcon is used
|
1547
|
// for selected
|
1548
|
_p.getIconSrc = function () {
|
1549
|
var behavior = this.getTree() ? this.getTree().getBehavior() : webFXTreeConfig.defaultBehavior;
|
1550
|
var open = behavior == "classic" && this.getExpanded() ||
|
1551
|
behavior != "classic" && this.isSelected();
|
1552
|
if (open && this.openIcon) {
|
1553
|
return this.openIcon;
|
1554
|
}
|
1555
|
if (!open && this.icon) {
|
1556
|
return this.icon;
|
1557
|
}
|
1558
|
|
1559
|
// fall back on default icons
|
1560
|
if (this.hasChildren()) {
|
1561
|
return open ? webFXTreeConfig.openFolderIcon : webFXTreeConfig.folderIcon;
|
1562
|
}
|
1563
|
return webFXTreeConfig.fileIcon;
|
1564
|
};
|
1565
|
|
1566
|
/* end tree model */
|
1567
|
|
1568
|
|
1569
|
|
1570
|
|
1571
|
if (window.attachEvent) {
|
1572
|
window.attachEvent("onunload", function () {
|
1573
|
for (var id in webFXTreeHandler.all)
|
1574
|
webFXTreeHandler.all[id].dispose();
|
1575
|
});
|
1576
|
}
|