VirtualBox

source: vbox/trunk/src/libs/dita-ot-1.8.5/doc/treeview.js@ 99507

最後變更 在這個檔案從99507是 98584,由 vboxsync 提交於 2 年 前

Docs: bugref:10302. Setting svn properties of DITA-OT library.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 47.9 KB
 
1/*
2This file is part of the DITA Open Toolkit project hosted on
3Sourceforge.net. See the accompanying license.txt file for
4applicable licenses.
5
6Copyright (c) 2006, Yahoo! Inc. All rights reserved.
7Code licensed under the BSD License:
8http://developer.yahoo.net/yui/license.txt
9version: 0.10.0
10*/
11
12/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
13
14/**
15 * Contains the tree view state data and the root node. This is an
16 * ordered tree; child nodes will be displayed in the order created, and
17 * there currently is no way to change this.
18 *
19 * @constructor
20 * @todo graft (appendBefore, appendAfter)
21 * @param {string} id The id of the element that the tree will be inserted
22 * into.
23 */
24YAHOO.widget.TreeView = function(id) {
25 if (id) { this.init(id); }
26};
27
28/**
29 * Count of all nodes in all trees
30 * @type int
31 */
32YAHOO.widget.TreeView.nodeCount = 0;
33
34YAHOO.widget.TreeView.prototype = {
35
36 /**
37 * The id of tree container element
38 *
39 * @type String
40 */
41 id: null,
42
43 /**
44 * Flat collection of all nodes in this tree
45 *
46 * @type Node[]
47 * @private
48 */
49 _nodes: null,
50
51 /**
52 * We lock the tree control while waiting for the dynamic loader to return
53 *
54 * @type boolean
55 */
56 locked: false,
57
58 /**
59 * The animation to use for expanding children, if any
60 *
61 * @type string
62 * @private
63 */
64 _expandAnim: null,
65
66 /**
67 * The animation to use for collapsing children, if any
68 *
69 * @type string
70 * @private
71 */
72 _collapseAnim: null,
73
74 /**
75 * The current number of animations that are executing
76 *
77 * @type int
78 * @private
79 */
80 _animCount: 0,
81
82 /**
83 * The maximum number of animations to run at one time.
84 *
85 * @type int
86 */
87 maxAnim: 2,
88
89 /**
90 * Sets up the animation for expanding children
91 *
92 * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
93 */
94 setExpandAnim: function(type) {
95 if (YAHOO.widget.TVAnim.isValid(type)) {
96 this._expandAnim = type;
97 }
98 },
99
100 /**
101 * Sets up the animation for collapsing children
102 *
103 * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
104 */
105 setCollapseAnim: function(type) {
106 if (YAHOO.widget.TVAnim.isValid(type)) {
107 this._collapseAnim = type;
108 }
109 },
110
111 /**
112 * Perform the expand animation if configured, or just show the
113 * element if not configured or too many animations are in progress
114 *
115 * @param el {HTMLElement} the element to animate
116 * @return {boolean} true if animation could be invoked, false otherwise
117 */
118 animateExpand: function(el) {
119
120 if (this._expandAnim && this._animCount < this.maxAnim) {
121 // this.locked = true;
122 var tree = this;
123 var a = YAHOO.widget.TVAnim.getAnim(this._expandAnim, el,
124 function() { tree.expandComplete(); });
125 if (a) {
126 ++this._animCount;
127 a.animate();
128 }
129
130 return true;
131 }
132
133 return false;
134 },
135
136 /**
137 * Perform the collapse animation if configured, or just show the
138 * element if not configured or too many animations are in progress
139 *
140 * @param el {HTMLElement} the element to animate
141 * @return {boolean} true if animation could be invoked, false otherwise
142 */
143 animateCollapse: function(el) {
144
145 if (this._collapseAnim && this._animCount < this.maxAnim) {
146 // this.locked = true;
147 var tree = this;
148 var a = YAHOO.widget.TVAnim.getAnim(this._collapseAnim, el,
149 function() { tree.collapseComplete(); });
150 if (a) {
151 ++this._animCount;
152 a.animate();
153 }
154
155 return true;
156 }
157
158 return false;
159 },
160
161 /**
162 * Function executed when the expand animation completes
163 */
164 expandComplete: function() {
165 --this._animCount;
166 // this.locked = false;
167 },
168
169 /**
170 * Function executed when the collapse animation completes
171 */
172 collapseComplete: function() {
173 --this._animCount;
174 // this.locked = false;
175 },
176
177 /**
178 * Initializes the tree
179 *
180 * @parm {string} id the id of the element that will hold the tree
181 * @private
182 */
183 init: function(id) {
184
185 this.id = id;
186 this._nodes = [];
187
188 // store a global reference
189 YAHOO.widget.TreeView.trees[id] = this;
190
191 // Set up the root node
192 this.root = new YAHOO.widget.RootNode(this);
193
194
195 },
196
197 /**
198 * Renders the tree boilerplate and visible nodes
199 */
200 draw: function() {
201 var html = this.root.getHtml();
202 if(document.getElementById(this.id))
203 document.getElementById(this.id).innerHTML = html;
204 /*document.getElementById(this.id).innerHTML = html;*/
205 this.firstDraw = false;
206 },
207
208 /**
209 * Nodes register themselves with the tree instance when they are created.
210 *
211 * @param node {Node} the node to register
212 * @private
213 */
214 regNode: function(node) {
215 this._nodes[node.index] = node;
216 },
217
218 /**
219 * Returns the root node of this tree
220 *
221 * @return {Node} the root node
222 */
223 getRoot: function() {
224 return this.root;
225 },
226
227 /**
228 * Configures this tree to dynamically load all child data
229 *
230 * @param {function} fnDataLoader the function that will be called to get the data
231 * @param iconMode {int} configures the icon that is displayed when a dynamic
232 * load node is expanded the first time without children. By default, the
233 * "collapse" icon will be used. If set to 1, the leaf node icon will be
234 * displayed.
235 */
236 setDynamicLoad: function(fnDataLoader, iconMode) {
237 this.root.setDynamicLoad(fnDataLoader, iconMode);
238 },
239
240 /**
241 * Expands all child nodes. Note: this conflicts with the "multiExpand"
242 * node property. If expand all is called in a tree with nodes that
243 * do not allow multiple siblings to be displayed, only the last sibling
244 * will be expanded.
245 */
246 expandAll: function() {
247 if (!this.locked) {
248 this.root.expandAll();
249 }
250 },
251
252 /**
253 * Collapses all expanded child nodes in the entire tree.
254 */
255 collapseAll: function() {
256 if (!this.locked) {
257 this.root.collapseAll();
258 }
259 },
260
261 /**
262 * Returns a node in the tree that has the specified index (this index
263 * is created internally, so this function probably will only be used
264 * in html generated for a given node.)
265 *
266 * @param {int} nodeIndex the index of the node wanted
267 * @return {Node} the node with index=nodeIndex, null if no match
268 */
269 getNodeByIndex: function(nodeIndex) {
270 var n = this._nodes[nodeIndex];
271 return (n) ? n : null;
272 },
273
274 /**
275 * Returns a node that has a matching property and value in the data
276 * object that was passed into its constructor. Provides a flexible
277 * way for the implementer to get a particular node.
278 *
279 * @param {object} property the property to search (usually a string)
280 * @param {object} value the value we want to find (usuall an int or string)
281 * @return {Node} the matching node, null if no match
282 */
283 getNodeByProperty: function(property, value) {
284 for (var i in this._nodes) {
285 var n = this._nodes[i];
286 if (n.data && value == n.data[property]) {
287 return n;
288 }
289 }
290
291 return null;
292 },
293
294 /**
295 * Removes the node and its children, and optionally refreshes the branch
296 * of the tree that was affected.
297 * @param {Node} The node to remove
298 * @param {boolean} autoRefresh automatically refreshes branch if true
299 * @return {boolean} False is there was a problem, true otherwise.
300 */
301 removeNode: function(node, autoRefresh) {
302
303 // Don't delete the root node
304 if (node.isRoot()) {
305 return false;
306 }
307
308 // Get the branch that we may need to refresh
309 var p = node.parent;
310 if (p.parent) {
311 p = p.parent;
312 }
313
314 // Delete the node and its children
315 this._deleteNode(node);
316
317 // Refresh the parent of the parent
318 if (autoRefresh && p && p.childrenRendered) {
319 p.refresh();
320 }
321
322 return true;
323 },
324
325 /**
326 * Deletes this nodes child collection, recursively. Also collapses
327 * the node, and resets the dynamic load flag. The primary use for
328 * this method is to purge a node and allow it to fetch its data
329 * dynamically again.
330 * @param {Node} node the node to purge
331 */
332 removeChildren: function(node) {
333 for (var i=0, len=node.children.length;i<len;++i) {
334 this._deleteNode(node.children[i]);
335 }
336
337 node.childrenRendered = false;
338 node.dynamicLoadComplete = false;
339 node.collapse();
340 },
341
342 /**
343 * Deletes the node and recurses children
344 * @private
345 */
346 _deleteNode: function(node) {
347 var p = node.parent;
348
349 // Remove all the child nodes first
350 this.removeChildren(node);
351
352 // Update the parent's collection of children
353 var a = [];
354
355 for (i=0, len=p.children.length;i<len;++i) {
356 if (p.children[i] != node) {
357 a[a.length] = p.children[i];
358 }
359 }
360
361 p.children = a;
362
363 // reset the childrenRendered flag for the parent
364 p.childrenRendered = false;
365
366 // Update the sibling relationship
367 if (node.previousSibling) {
368 node.previousSibling.nextSibling = node.nextSibling;
369 }
370
371 if (node.nextSibling) {
372 node.nextSibling.previousSibling = node.previousSibling;
373 }
374
375 // Update the tree's node collection
376 delete this._nodes[node.index];
377 },
378
379 /**
380 * Abstract method that is executed when a node is expanded
381 *
382 * @param node {Node} the node that was expanded
383 */
384 onExpand: function(node) { },
385
386 /**
387 * Abstract method that is executed when a node is collapsed
388 *
389 * @param node {Node} the node that was collapsed.
390 */
391 onCollapse: function(node) { }
392
393};
394
395/**
396 * Global cache of tree instances
397 *
398 * @type Array
399 * @private
400 */
401YAHOO.widget.TreeView.trees = [];
402
403/**
404 * Global method for getting a tree by its id. Used in the generated
405 * tree html.
406 *
407 * @param treeId {String} the id of the tree instance
408 * @return {TreeView} the tree instance requested, null if not found.
409 */
410YAHOO.widget.TreeView.getTree = function(treeId) {
411 var t = YAHOO.widget.TreeView.trees[treeId];
412 return (t) ? t : null;
413};
414
415/**
416 * Global method for getting a node by its id. Used in the generated
417 * tree html.
418 *
419 * @param treeId {String} the id of the tree instance
420 * @param nodeIndex {String} the index of the node to return
421 * @return {Node} the node instance requested, null if not found
422 */
423YAHOO.widget.TreeView.getNode = function(treeId, nodeIndex) {
424 var t = YAHOO.widget.TreeView.getTree(treeId);
425 return (t) ? t.getNodeByIndex(nodeIndex) : null;
426};
427
428/**
429 * Adds an event. Replace with event manager when available
430 *
431 * @param el the elment to bind the handler to
432 * @param {string} sType the type of event handler
433 * @param {function} fn the callback to invoke
434 * @param {boolean} capture if true event is capture phase, bubble otherwise
435 */
436YAHOO.widget.TreeView.addHandler = function (el, sType, fn, capture) {
437 capture = (capture) ? true : false;
438 if (el.addEventListener) {
439 el.addEventListener(sType, fn, capture);
440 } else if (el.attachEvent) {
441 el.attachEvent("on" + sType, fn);
442 } else {
443 el["on" + sType] = fn;
444 }
445};
446
447/**
448 * Attempts to preload the images defined in the styles used to draw the tree by
449 * rendering off-screen elements that use the styles.
450 */
451YAHOO.widget.TreeView.preload = function() {
452
453 var styles = [
454 "ygtvtn",
455 "ygtvtm",
456 "ygtvtmh",
457 "ygtvtp",
458 "ygtvtph",
459 "ygtvln",
460 "ygtvlm",
461 "ygtvlmh",
462 "ygtvlp",
463 "ygtvlph",
464 "ygtvloading"
465 ];
466
467 var sb = [];
468
469 for (var i = 0; i < styles.length; ++i) {
470 sb[sb.length] = '<span class="' + styles[i] + '">&nbsp;</span>';
471 }
472
473 var f = document.createElement("div");
474 var s = f.style;
475 s.position = "absolute";
476 s.top = "-1000px";
477 s.left = "-1000px";
478 f.innerHTML = sb.join("");
479
480 document.body.appendChild(f);
481};
482
483YAHOO.widget.TreeView.addHandler(window,
484 "load", YAHOO.widget.TreeView.preload);
485
486/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
487
488/**
489 * The base class for all tree nodes. The node's presentation and behavior in
490 * response to mouse events is handled in Node subclasses.
491 *
492 * @param oData {object} a string or object containing the data that will
493 * be used to render this node
494 * @param oParent {Node} this node's parent node
495 * @param expanded {boolean} the initial expanded/collapsed state
496 * @constructor
497 */
498YAHOO.widget.Node = function(oData, oParent, expanded) {
499 if (oParent) { this.init(oData, oParent, expanded); }
500};
501
502YAHOO.widget.Node.prototype = {
503
504 /**
505 * The index for this instance obtained from global counter in YAHOO.widget.TreeView.
506 *
507 * @type int
508 */
509 index: 0,
510
511 /**
512 * This node's child node collection.
513 *
514 * @type Node[]
515 */
516 children: null,
517
518 /**
519 * Tree instance this node is part of
520 *
521 * @type TreeView
522 */
523 tree: null,
524
525 /**
526 * The data linked to this node. This can be any object or primitive
527 * value, and the data can be used in getNodeHtml().
528 *
529 * @type object
530 */
531 data: null,
532
533 /**
534 * Parent node
535 *
536 * @type Node
537 */
538 parent: null,
539
540 /**
541 * The depth of this node. We start at -1 for the root node.
542 *
543 * @type int
544 */
545 depth: -1,
546
547 /**
548 * The href for the node's label. If one is not specified, the href will
549 * be set so that it toggles the node.
550 *
551 * @type string
552 */
553 href: null,
554
555 /**
556 * The label href target, defaults to current window
557 *
558 * @type string
559 */
560 target: "_self",
561
562 /**
563 * The node's expanded/collapsed state
564 *
565 * @type boolean
566 */
567 expanded: false,
568
569 /**
570 * Can multiple children be expanded at once?
571 *
572 * @type boolean
573 */
574 multiExpand: true,
575
576 /**
577 * Should we render children for a collapsed node? It is possible that the
578 * implementer will want to render the hidden data... @todo verify that we
579 * need this, and implement it if we do.
580 *
581 * @type boolean
582 */
583 renderHidden: false,
584
585 /**
586 * This flag is set to true when the html is generated for this node's
587 * children, and set to false when new children are added.
588 * @type boolean
589 */
590 childrenRendered: false,
591
592 /**
593 * Dynamically loaded nodes only fetch the data the first time they are
594 * expanded. This flag is set to true once the data has been fetched.
595 * @type boolean
596 */
597 dynamicLoadComplete: false,
598
599 /**
600 * This node's previous sibling
601 *
602 * @type Node
603 */
604 previousSibling: null,
605
606 /**
607 * This node's next sibling
608 *
609 * @type Node
610 */
611 nextSibling: null,
612
613 /**
614 * We can set the node up to call an external method to get the child
615 * data dynamically.
616 *
617 * @type boolean
618 * @private
619 */
620 _dynLoad: false,
621
622 /**
623 * Function to execute when we need to get this node's child data.
624 *
625 * @type function
626 */
627 dataLoader: null,
628
629 /**
630 * This is true for dynamically loading nodes while waiting for the
631 * callback to return.
632 *
633 * @type boolean
634 */
635 isLoading: false,
636
637 /**
638 * The toggle/branch icon will not show if this is set to false. This
639 * could be useful if the implementer wants to have the child contain
640 * extra info about the parent, rather than an actual node.
641 *
642 * @type boolean
643 */
644 hasIcon: true,
645
646 /**
647 * Used to configure what happens when a dynamic load node is expanded
648 * and we discover that it does not have children. By default, it is
649 * treated as if it still could have children (plus/minus icon). Set
650 * iconMode to have it display like a leaf node instead.
651 * @type int
652 */
653 iconMode: 0,
654
655 /**
656 * The node type
657 * @private
658 */
659 _type: "Node",
660
661 /*
662 spacerPath: "http://us.i1.yimg.com/us.yimg.com/i/space.gif",
663 expandedText: "Expanded",
664 collapsedText: "Collapsed",
665 loadingText: "Loading",
666 */
667
668 /**
669 * Initializes this node, gets some of the properties from the parent
670 *
671 * @param oData {object} a string or object containing the data that will
672 * be used to render this node
673 * @param oParent {Node} this node's parent node
674 * @param expanded {boolean} the initial expanded/collapsed state
675 */
676 init: function(oData, oParent, expanded) {
677 this.data = oData;
678 this.children = [];
679 this.index = YAHOO.widget.TreeView.nodeCount;
680 ++YAHOO.widget.TreeView.nodeCount;
681 this.expanded = expanded;
682
683 // oParent should never be null except when we create the root node.
684 if (oParent) {
685 this.tree = oParent.tree;
686 this.parent = oParent;
687 this.href = "javascript:" + this.getToggleLink();
688 this.depth = oParent.depth + 1;
689 this.multiExpand = oParent.multiExpand;
690
691 oParent.appendChild(this);
692 }
693 },
694
695 /**
696 * Appends a node to the child collection.
697 *
698 * @param node {Node} the new node
699 * @return {Node} the child node
700 * @private
701 * @TODO insertBefore, insertAfter
702 */
703 appendChild: function(node) {
704 if (this.hasChildren()) {
705 var sib = this.children[this.children.length - 1];
706 sib.nextSibling = node;
707 node.previousSibling = sib;
708 }
709
710 this.tree.regNode(node);
711 this.children[this.children.length] = node;
712 this.childrenRendered = false;
713 return node;
714
715 },
716
717 /**
718 * Returns a node array of this node's siblings, null if none.
719 *
720 * @return Node[]
721 */
722 getSiblings: function() {
723 return this.parent.children;
724 },
725
726 /**
727 * Shows this node's children
728 */
729 showChildren: function() {
730 if (!this.tree.animateExpand(this.getChildrenEl())) {
731 if (this.hasChildren()) {
732 this.getChildrenEl().style.display = "";
733 }
734 }
735 },
736
737 /**
738 * Hides this node's children
739 */
740 hideChildren: function() {
741
742 if (!this.tree.animateCollapse(this.getChildrenEl())) {
743 this.getChildrenEl().style.display = "none";
744 }
745 },
746
747 /**
748 * Returns the id for this node's container div
749 *
750 * @return {string} the element id
751 */
752 getElId: function() {
753 return "ygtv" + this.index;
754 },
755
756 /**
757 * Returns the id for this node's children div
758 *
759 * @return {string} the element id for this node's children div
760 */
761 getChildrenElId: function() {
762 return "ygtvc" + this.index;
763 },
764
765 /**
766 * Returns the id for this node's toggle element
767 *
768 * @return {string} the toggel element id
769 */
770 getToggleElId: function() {
771 return "ygtvt" + this.index;
772 },
773
774 /**
775 * Returns the id for this node's spacer image. The spacer is positioned
776 * over the toggle and provides feedback for screen readers.
777 * @return {string} the id for the spacer image
778 */
779 /*
780 getSpacerId: function() {
781 return "ygtvspacer" + this.index;
782 },
783 */
784
785 /**
786 * Returns this node's container html element
787 * @return {HTMLElement} the container html element
788 */
789 getEl: function() {
790 return document.getElementById(this.getElId());
791 },
792
793 /**
794 * Returns the div that was generated for this node's children
795 * @return {HTMLElement} this node's children div
796 */
797 getChildrenEl: function() {
798 return document.getElementById(this.getChildrenElId());
799 },
800
801 /**
802 * Returns the element that is being used for this node's toggle.
803 * @return {HTMLElement} this node's toggle html element
804 */
805 getToggleEl: function() {
806 return document.getElementById(this.getToggleElId());
807 },
808
809 /**
810 * Returns the element that is being used for this node's spacer.
811 * @return {HTMLElement} this node's spacer html element
812 */
813 /*
814 getSpacer: function() {
815 return document.getElementById( this.getSpacerId() ) || {};
816 },
817 */
818
819 /*
820 getStateText: function() {
821 if (this.isLoading) {
822 return this.loadingText;
823 } else if (this.hasChildren(true)) {
824 if (this.expanded) {
825 return this.expandedText;
826 } else {
827 return this.collapsedText;
828 }
829 } else {
830 return "";
831 }
832 },
833 */
834
835 /**
836 * Generates the link that will invoke this node's toggle method
837 * @return {string} the javascript url for toggling this node
838 */
839 getToggleLink: function() {
840 return "YAHOO.widget.TreeView.getNode(\'" + this.tree.id + "\'," +
841 this.index + ").toggle()";
842 },
843
844 /**
845 * Hides this nodes children (creating them if necessary), changes the
846 * toggle style.
847 */
848 collapse: function() {
849 // Only collapse if currently expanded
850 if (!this.expanded) { return; }
851
852 // fire the collapse event handler
853 var ret = this.tree.onCollapse(this);
854
855 if ("undefined" != typeof ret && !ret) {
856 return;
857 }
858
859 if (!this.getEl()) {
860 this.expanded = false;
861 return;
862 }
863
864 // hide the child div
865 this.hideChildren();
866 this.expanded = false;
867
868 if (this.hasIcon) {
869 this.getToggleEl().className = this.getStyle();
870 }
871
872 // this.getSpacer().title = this.getStateText();
873
874 },
875
876 /**
877 * Shows this nodes children (creating them if necessary), changes the
878 * toggle style, and collapses its siblings if multiExpand is not set.
879 */
880 expand: function() {
881 // Only expand if currently collapsed.
882 if (this.expanded) { return; }
883
884 // fire the expand event handler
885 var ret = this.tree.onExpand(this);
886
887 if ("undefined" != typeof ret && !ret) {
888 return;
889 }
890
891 if (!this.getEl()) {
892 this.expanded = true;
893 return;
894 }
895
896 if (! this.childrenRendered) {
897 this.getChildrenEl().innerHTML = this.renderChildren();
898 } else {
899 }
900
901 this.expanded = true;
902 if (this.hasIcon) {
903 this.getToggleEl().className = this.getStyle();
904 }
905
906 // this.getSpacer().title = this.getStateText();
907
908 // We do an extra check for children here because the lazy
909 // load feature can expose nodes that have no children.
910
911 // if (!this.hasChildren()) {
912 if (this.isLoading) {
913 this.expanded = false;
914 return;
915 }
916
917 if (! this.multiExpand) {
918 var sibs = this.getSiblings();
919 for (var i=0; i<sibs.length; ++i) {
920 if (sibs[i] != this && sibs[i].expanded) {
921 sibs[i].collapse();
922 }
923 }
924 }
925
926 this.showChildren();
927 },
928
929 /**
930 * Returns the css style name for the toggle
931 *
932 * @return {string} the css class for this node's toggle
933 */
934 getStyle: function() {
935 if (this.isLoading) {
936 return "ygtvloading";
937 } else {
938 // location top or bottom, middle nodes also get the top style
939 var loc = (this.nextSibling) ? "t" : "l";
940
941 // type p=plus(expand), m=minus(collapase), n=none(no children)
942 var type = "n";
943 if (this.hasChildren(true) || (this.isDynamic() && !this.getIconMode())) {
944 // if (this.hasChildren(true)) {
945 type = (this.expanded) ? "m" : "p";
946 }
947
948 return "ygtv" + loc + type;
949 }
950 },
951
952 /**
953 * Returns the hover style for the icon
954 * @return {string} the css class hover state
955 */
956 getHoverStyle: function() {
957 var s = this.getStyle();
958 if (this.hasChildren(true) && !this.isLoading) {
959 s += "h";
960 }
961 return s;
962 },
963
964 /**
965 * Recursively expands all of this node's children.
966 */
967 expandAll: function() {
968 for (var i=0;i<this.children.length;++i) {
969 var c = this.children[i];
970 if (c.isDynamic()) {
971 alert("Not supported (lazy load + expand all)");
972 break;
973 } else if (! c.multiExpand) {
974 alert("Not supported (no multi-expand + expand all)");
975 break;
976 } else {
977 c.expand();
978 c.expandAll();
979 }
980 }
981 },
982
983 /**
984 * Recursively collapses all of this node's children.
985 */
986 collapseAll: function() {
987 for (var i=0;i<this.children.length;++i) {
988 this.children[i].collapse();
989 this.children[i].collapseAll();
990 }
991 },
992
993 /**
994 * Configures this node for dynamically obtaining the child data
995 * when the node is first expanded. Calling it without the callback
996 * will turn off dynamic load for the node.
997 *
998 * @param fmDataLoader {function} the function that will be used to get the data.
999 * @param iconMode {int} configures the icon that is displayed when a dynamic
1000 * load node is expanded the first time without children. By default, the
1001 * "collapse" icon will be used. If set to 1, the leaf node icon will be
1002 * displayed.
1003 */
1004 setDynamicLoad: function(fnDataLoader, iconMode) {
1005 if (fnDataLoader) {
1006 this.dataLoader = fnDataLoader;
1007 this._dynLoad = true;
1008 } else {
1009 this.dataLoader = null;
1010 this._dynLoad = false;
1011 }
1012
1013 if (iconMode) {
1014 this.iconMode = iconMode;
1015 }
1016 },
1017
1018 /**
1019 * Evaluates if this node is the root node of the tree
1020 *
1021 * @return {boolean} true if this is the root node
1022 */
1023 isRoot: function() {
1024 return (this == this.tree.root);
1025 },
1026
1027 /**
1028 * Evaluates if this node's children should be loaded dynamically. Looks for
1029 * the property both in this instance and the root node. If the tree is
1030 * defined to load all children dynamically, the data callback function is
1031 * defined in the root node
1032 *
1033 * @return {boolean} true if this node's children are to be loaded dynamically
1034 */
1035 isDynamic: function() {
1036 var lazy = (!this.isRoot() && (this._dynLoad || this.tree.root._dynLoad));
1037 return lazy;
1038 },
1039
1040 getIconMode: function() {
1041 return (this.iconMode || this.tree.root.iconMode);
1042 },
1043
1044 /**
1045 * Checks if this node has children. If this node is lazy-loading and the
1046 * children have not been rendered, we do not know whether or not there
1047 * are actual children. In most cases, we need to assume that there are
1048 * children (for instance, the toggle needs to show the expandable
1049 * presentation state). In other times we want to know if there are rendered
1050 * children. For the latter, "checkForLazyLoad" should be false.
1051 *
1052 * @param checkForLazyLoad {boolean} should we check for unloaded children?
1053 * @return {boolean} true if this has children or if it might and we are
1054 * checking for this condition.
1055 */
1056 hasChildren: function(checkForLazyLoad) {
1057 return ( this.children.length > 0 ||
1058 (checkForLazyLoad && this.isDynamic() && !this.dynamicLoadComplete) );
1059 },
1060
1061 /**
1062 * Expands if node is collapsed, collapses otherwise.
1063 */
1064 toggle: function() {
1065 if (!this.tree.locked && ( this.hasChildren(true) || this.isDynamic()) ) {
1066 if (this.expanded) { this.collapse(); } else { this.expand(); }
1067 }
1068 },
1069
1070 /**
1071 * Returns the markup for this node and its children.
1072 *
1073 * @return {string} the markup for this node and its expanded children.
1074 */
1075 getHtml: function() {
1076 var sb = [];
1077 sb[sb.length] = '<div class="ygtvitem" id="' + this.getElId() + '">';
1078 sb[sb.length] = this.getNodeHtml();
1079 sb[sb.length] = this.getChildrenHtml();
1080 sb[sb.length] = '</div>';
1081 return sb.join("");
1082 },
1083
1084 /**
1085 * Called when first rendering the tree. We always build the div that will
1086 * contain this nodes children, but we don't render the children themselves
1087 * unless this node is expanded.
1088 *
1089 * @return {string} the children container div html and any expanded children
1090 * @private
1091 */
1092 getChildrenHtml: function() {
1093
1094 var sb = [];
1095 sb[sb.length] = '<div class="ygtvchildren"';
1096 sb[sb.length] = ' id="' + this.getChildrenElId() + '"';
1097 if (!this.expanded) {
1098 sb[sb.length] = ' style="display:none;"';
1099 }
1100 sb[sb.length] = '>';
1101
1102 // Don't render the actual child node HTML unless this node is expanded.
1103 if ( (this.hasChildren(true) && this.expanded) ||
1104 (this.renderHidden && !this.isDynamic()) ) {
1105 sb[sb.length] = this.renderChildren();
1106 }
1107
1108 sb[sb.length] = '</div>';
1109
1110 return sb.join("");
1111 },
1112
1113 /**
1114 * Generates the markup for the child nodes. This is not done until the node
1115 * is expanded.
1116 *
1117 * @return {string} the html for this node's children
1118 * @private
1119 */
1120 renderChildren: function() {
1121
1122
1123 var node = this;
1124
1125 if (this.isDynamic() && !this.dynamicLoadComplete) {
1126 this.isLoading = true;
1127 this.tree.locked = true;
1128
1129 if (this.dataLoader) {
1130
1131 setTimeout(
1132 function() {
1133 node.dataLoader(node,
1134 function() {
1135 node.loadComplete();
1136 });
1137 }, 10);
1138
1139 } else if (this.tree.root.dataLoader) {
1140
1141 setTimeout(
1142 function() {
1143 node.tree.root.dataLoader(node,
1144 function() {
1145 node.loadComplete();
1146 });
1147 }, 10);
1148
1149 } else {
1150 return "Error: data loader not found or not specified.";
1151 }
1152
1153 return "";
1154
1155 } else {
1156 return this.completeRender();
1157 }
1158 },
1159
1160 /**
1161 * Called when we know we have all the child data.
1162 * @return {string} children html
1163 */
1164 completeRender: function() {
1165 var sb = [];
1166
1167 for (var i=0; i < this.children.length; ++i) {
1168 this.children[i].childrenRendered = false;
1169 sb[sb.length] = this.children[i].getHtml();
1170 }
1171
1172 this.childrenRendered = true;
1173
1174 return sb.join("");
1175 },
1176
1177 /**
1178 * Load complete is the callback function we pass to the data provider
1179 * in dynamic load situations.
1180 */
1181 loadComplete: function() {
1182 this.getChildrenEl().innerHTML = this.completeRender();
1183 this.dynamicLoadComplete = true;
1184 this.isLoading = false;
1185 this.expand();
1186 this.tree.locked = false;
1187 },
1188
1189 /**
1190 * Returns this node's ancestor at the specified depth.
1191 *
1192 * @param {int} depth the depth of the ancestor.
1193 * @return {Node} the ancestor
1194 */
1195 getAncestor: function(depth) {
1196 if (depth >= this.depth || depth < 0) {
1197 return null;
1198 }
1199
1200 var p = this.parent;
1201
1202 while (p.depth > depth) {
1203 p = p.parent;
1204 }
1205
1206 return p;
1207 },
1208
1209 /**
1210 * Returns the css class for the spacer at the specified depth for
1211 * this node. If this node's ancestor at the specified depth
1212 * has a next sibling the presentation is different than if it
1213 * does not have a next sibling
1214 *
1215 * @param {int} depth the depth of the ancestor.
1216 * @return {string} the css class for the spacer
1217 */
1218 getDepthStyle: function(depth) {
1219 return (this.getAncestor(depth).nextSibling) ?
1220 "ygtvdepthcell" : "ygtvblankdepthcell";
1221 },
1222
1223 /**
1224 * Get the markup for the node. This is designed to be overrided so that we can
1225 * support different types of nodes.
1226 *
1227 * @return {string} The HTML that will render this node.
1228 */
1229 getNodeHtml: function() {
1230 return "";
1231 },
1232
1233 /**
1234 * Regenerates the html for this node and its children. To be used when the
1235 * node is expanded and new children have been added.
1236 */
1237 refresh: function() {
1238 // this.loadComplete();
1239 this.getChildrenEl().innerHTML = this.completeRender();
1240
1241 if (this.hasIcon) {
1242 var el = this.getToggleEl();
1243 if (el) {
1244 el.className = this.getStyle();
1245 }
1246 }
1247 }
1248
1249};
1250
1251/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1252
1253/**
1254 * A custom YAHOO.widget.Node that handles the unique nature of
1255 * the virtual, presentationless root node.
1256 *
1257 * @extends YAHOO.widget.Node
1258 * @constructor
1259 */
1260YAHOO.widget.RootNode = function(oTree) {
1261 // Initialize the node with null params. The root node is a
1262 // special case where the node has no presentation. So we have
1263 // to alter the standard properties a bit.
1264 this.init(null, null, true);
1265
1266 /**
1267 * For the root node, we get the tree reference from as a param
1268 * to the constructor instead of from the parent element.
1269 *
1270 * @type TreeView
1271 */
1272 this.tree = oTree;
1273};
1274YAHOO.widget.RootNode.prototype = new YAHOO.widget.Node();
1275
1276// overrides YAHOO.widget.Node
1277YAHOO.widget.RootNode.prototype.getNodeHtml = function() {
1278 return "";
1279};
1280
1281/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1282
1283/**
1284 * The default node presentation. The first parameter should be
1285 * either a string that will be used as the node's label, or an object
1286 * that has a string propery called label. By default, the clicking the
1287 * label will toggle the expanded/collapsed state of the node. By
1288 * changing the href property of the instance, this behavior can be
1289 * changed so that the label will go to the specified href.
1290 *
1291 * @extends YAHOO.widget.Node
1292 * @constructor
1293 * @param oData {object} a string or object containing the data that will
1294 * be used to render this node
1295 * @param oParent {YAHOO.widget.Node} this node's parent node
1296 * @param expanded {boolean} the initial expanded/collapsed state
1297 */
1298YAHOO.widget.TextNode = function(oData, oParent, expanded) {
1299 this.type = "TextNode";
1300
1301 if (oParent) {
1302 this.init(oData, oParent, expanded);
1303 this.setUpLabel(oData);
1304 }
1305};
1306
1307YAHOO.widget.TextNode.prototype = new YAHOO.widget.Node();
1308
1309/**
1310 * The CSS class for the label href. Defaults to ygtvlabel, but can be
1311 * overridden to provide a custom presentation for a specific node.
1312 *
1313 * @type string
1314 */
1315YAHOO.widget.TextNode.prototype.labelStyle = "ygtvlabel";
1316
1317/**
1318 * The derived element id of the label for this node
1319 *
1320 * @type string
1321 */
1322YAHOO.widget.TextNode.prototype.labelElId = null;
1323
1324/**
1325 * The text for the label. It is assumed that the oData parameter will
1326 * either be a string that will be used as the label, or an object that
1327 * has a property called "label" that we will use.
1328 *
1329 * @type string
1330 */
1331YAHOO.widget.TextNode.prototype.label = null;
1332
1333/**
1334 * Sets up the node label
1335 *
1336 * @param oData string containing the label, or an object with a label property
1337 */
1338YAHOO.widget.TextNode.prototype.setUpLabel = function(oData) {
1339 if (typeof oData == "string") {
1340 oData = { label: oData };
1341 }
1342 this.label = oData.label;
1343
1344 // update the link
1345 if (oData.href) {
1346 this.href = oData.href;
1347 }
1348
1349 // set the target
1350 if (oData.target) {
1351 this.target = oData.target;
1352 }
1353
1354 if (oData.style) {
1355 this.labelStyle = oData.style;
1356 }
1357
1358 this.labelElId = "ygtvlabelel" + this.index;
1359};
1360
1361/**
1362 * Returns the label element
1363 *
1364 * @return {object} the element
1365 */
1366YAHOO.widget.TextNode.prototype.getLabelEl = function() {
1367 return document.getElementById(this.labelElId);
1368};
1369
1370// overrides YAHOO.widget.Node
1371YAHOO.widget.TextNode.prototype.getNodeHtml = function() {
1372 var sb = [];
1373
1374 sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
1375 sb[sb.length] = '<tr>';
1376
1377 for (i=0;i<this.depth;++i) {
1378 // sb[sb.length] = '<td class="ygtvdepthcell">&nbsp;</td>';
1379 sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
1380 }
1381
1382 var getNode = 'YAHOO.widget.TreeView.getNode(\'' +
1383 this.tree.id + '\',' + this.index + ')';
1384
1385 sb[sb.length] = '<td';
1386 // sb[sb.length] = ' onselectstart="return false"';
1387 sb[sb.length] = ' id="' + this.getToggleElId() + '"';
1388 sb[sb.length] = ' class="' + this.getStyle() + '"';
1389 if (this.hasChildren(true)) {
1390 sb[sb.length] = ' onmouseover="this.className=';
1391 sb[sb.length] = getNode + '.getHoverStyle()"';
1392 sb[sb.length] = ' onmouseout="this.className=';
1393 sb[sb.length] = getNode + '.getStyle()"';
1394 }
1395
1396
1397 sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">';
1398
1399 /*
1400 sb[sb.length] = '<img id="' + this.getSpacerId() + '"';
1401 sb[sb.length] = ' alt=""';
1402 sb[sb.length] = ' tabindex=0';
1403 sb[sb.length] = ' src="' + this.spacerPath + '"';
1404 sb[sb.length] = ' title="' + this.getStateText() + '"';
1405 sb[sb.length] = ' class="ygtvspacer"';
1406 // sb[sb.length] = ' onkeypress="return ' + getNode + '".onKeyPress()"';
1407 sb[sb.length] = ' />';
1408 */
1409
1410 sb[sb.length] = '&nbsp;';
1411
1412 sb[sb.length] = '</td>';
1413 sb[sb.length] = '<td>';
1414 sb[sb.length] = '<a';
1415 sb[sb.length] = ' id="' + this.labelElId + '"';
1416 sb[sb.length] = ' class="' + this.labelStyle + '"';
1417 sb[sb.length] = ' href="' + this.href + '"';
1418 sb[sb.length] = ' target="' + this.target + '"';
1419
1420 sb[sb.length] = ' onclick="return ' + getNode + '.onLabelClick(' + getNode +')"';
1421 /*sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '.onLabelClick(' + getNode
1422 +')"';*/
1423
1424 if (this.hasChildren(true)) {
1425 sb[sb.length] = ' onmouseover="document.getElementById(\'';
1426 sb[sb.length] = this.getToggleElId() + '\').className=';
1427 sb[sb.length] = getNode + '.getHoverStyle()"';
1428 sb[sb.length] = ' onmouseout="document.getElementById(\'';
1429 sb[sb.length] = this.getToggleElId() + '\').className=';
1430 sb[sb.length] = getNode + '.getStyle()"';
1431 }
1432 sb[sb.length] = ' >';
1433 sb[sb.length] = this.label;
1434 sb[sb.length] = '</a>';
1435 sb[sb.length] = '</td>';
1436 sb[sb.length] = '</tr>';
1437 sb[sb.length] = '</table>';
1438
1439 return sb.join("");
1440};
1441
1442/**
1443 * Executed when the label is clicked
1444 * @param me {Node} this node
1445 * @scope the anchor tag clicked
1446 * @return false to cancel the anchor click
1447 */
1448YAHOO.widget.TextNode.prototype.onLabelClick = function(me) {
1449 //return true;
1450};
1451/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1452
1453/**
1454 * A menu-specific implementation that differs from TextNode in that only
1455 * one sibling can be expanded at a time.
1456 * @extends YAHOO.widget.TextNode
1457 * @constructor
1458 */
1459YAHOO.widget.MenuNode = function(oData, oParent, expanded) {
1460 if (oParent) {
1461 this.init(oData, oParent, expanded);
1462 this.setUpLabel(oData);
1463 }
1464
1465 /**
1466 * Menus usually allow only one branch to be open at a time.
1467 * @type boolean
1468 */
1469 this.multiExpand = false;
1470
1471};
1472
1473YAHOO.widget.MenuNode.prototype = new YAHOO.widget.TextNode();
1474
1475/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1476
1477/**
1478 * This implementation takes either a string or object for the
1479 * oData argument. If is it a string, we will use it for the display
1480 * of this node (and it can contain any html code). If the parameter
1481 * is an object, we look for a parameter called "html" that will be
1482 * used for this node's display.
1483 *
1484 * @extends YAHOO.widget.Node
1485 * @constructor
1486 * @param oData {object} a string or object containing the data that will
1487 * be used to render this node
1488 * @param oParent {YAHOO.widget.Node} this node's parent node
1489 * @param expanded {boolean} the initial expanded/collapsed state
1490 * @param hasIcon {boolean} specifies whether or not leaf nodes should
1491 * have an icon
1492 */
1493YAHOO.widget.HTMLNode = function(oData, oParent, expanded, hasIcon) {
1494 if (oParent) {
1495 this.init(oData, oParent, expanded);
1496 this.initContent(oData, hasIcon);
1497 }
1498};
1499
1500YAHOO.widget.HTMLNode.prototype = new YAHOO.widget.Node();
1501
1502/**
1503 * The CSS class for the label href. Defaults to ygtvlabel, but can be
1504 * overridden to provide a custom presentation for a specific node.
1505 *
1506 * @type string
1507 */
1508YAHOO.widget.HTMLNode.prototype.contentStyle = "ygtvhtml";
1509
1510/**
1511 * The generated id that will contain the data passed in by the implementer.
1512 *
1513 * @type string
1514 */
1515YAHOO.widget.HTMLNode.prototype.contentElId = null;
1516
1517/**
1518 * The HTML content to use for this node's display
1519 *
1520 * @type string
1521 */
1522YAHOO.widget.HTMLNode.prototype.content = null;
1523
1524/**
1525 * Sets up the node label
1526 *
1527 * @param {object} An html string or object containing an html property
1528 * @param {boolean} hasIcon determines if the node will be rendered with an
1529 * icon or not
1530 */
1531YAHOO.widget.HTMLNode.prototype.initContent = function(oData, hasIcon) {
1532 if (typeof oData == "string") {
1533 oData = { html: oData };
1534 }
1535
1536 this.html = oData.html;
1537 this.contentElId = "ygtvcontentel" + this.index;
1538 this.hasIcon = hasIcon;
1539};
1540
1541/**
1542 * Returns the outer html element for this node's content
1543 *
1544 * @return {HTMLElement} the element
1545 */
1546YAHOO.widget.HTMLNode.prototype.getContentEl = function() {
1547 return document.getElementById(this.contentElId);
1548};
1549
1550// overrides YAHOO.widget.Node
1551YAHOO.widget.HTMLNode.prototype.getNodeHtml = function() {
1552 var sb = [];
1553
1554 sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
1555 sb[sb.length] = '<tr>';
1556
1557 for (i=0;i<this.depth;++i) {
1558 sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
1559 }
1560
1561 if (this.hasIcon) {
1562 sb[sb.length] = '<td';
1563 sb[sb.length] = ' id="' + this.getToggleElId() + '"';
1564 sb[sb.length] = ' class="' + this.getStyle() + '"';
1565 sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '"';
1566 if (this.hasChildren(true)) {
1567 sb[sb.length] = ' onmouseover="this.className=';
1568 sb[sb.length] = 'YAHOO.widget.TreeView.getNode(\'';
1569 sb[sb.length] = this.tree.id + '\',' + this.index + ').getHoverStyle()"';
1570 sb[sb.length] = ' onmouseout="this.className=';
1571 sb[sb.length] = 'YAHOO.widget.TreeView.getNode(\'';
1572 sb[sb.length] = this.tree.id + '\',' + this.index + ').getStyle()"';
1573 }
1574 sb[sb.length] = '>&nbsp;</td>';
1575 }
1576
1577 sb[sb.length] = '<td';
1578 sb[sb.length] = ' id="' + this.contentElId + '"';
1579 sb[sb.length] = ' class="' + this.contentStyle + '"';
1580 sb[sb.length] = ' >';
1581 sb[sb.length] = this.html;
1582 sb[sb.length] = '</td>';
1583 sb[sb.length] = '</tr>';
1584 sb[sb.length] = '</table>';
1585
1586 return sb.join("");
1587};
1588
1589/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1590
1591/**
1592 * A static factory class for tree view expand/collapse animations
1593 *
1594 * @constructor
1595 */
1596YAHOO.widget.TVAnim = function() {
1597 return {
1598 /**
1599 * Constant for the fade in animation
1600 *
1601 * @type string
1602 */
1603 FADE_IN: "TVFadeIn",
1604
1605 /**
1606 * Constant for the fade out animation
1607 *
1608 * @type string
1609 */
1610 FADE_OUT: "TVFadeOut",
1611
1612 /**
1613 * Returns a ygAnim instance of the given type
1614 *
1615 * @param type {string} the type of animation
1616 * @param el {HTMLElement} the element to element (probably the children div)
1617 * @param callback {function} function to invoke when the animation is done.
1618 * @return {YAHOO.util.Animation} the animation instance
1619 */
1620 getAnim: function(type, el, callback) {
1621 if (YAHOO.widget[type]) {
1622 return new YAHOO.widget[type](el, callback);
1623 } else {
1624 return null;
1625 }
1626 },
1627
1628 /**
1629 * Returns true if the specified animation class is available
1630 *
1631 * @param type {string} the type of animation
1632 * @return {boolean} true if valid, false if not
1633 */
1634 isValid: function(type) {
1635 return (YAHOO.widget[type]);
1636 }
1637 };
1638} ();
1639
1640/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1641
1642/**
1643 * A 1/2 second fade-in animation.
1644 *
1645 * @constructor
1646 * @param el {HTMLElement} the element to animate
1647 * @param callback {function} function to invoke when the animation is finished
1648 */
1649YAHOO.widget.TVFadeIn = function(el, callback) {
1650 /**
1651 * The element to animate
1652 * @type HTMLElement
1653 */
1654 this.el = el;
1655
1656 /**
1657 * the callback to invoke when the animation is complete
1658 *
1659 * @type function
1660 */
1661 this.callback = callback;
1662
1663 /**
1664 * @private
1665 */
1666};
1667
1668/**
1669 * Performs the animation
1670 */
1671YAHOO.widget.TVFadeIn.prototype = {
1672 animate: function() {
1673 var tvanim = this;
1674
1675 var s = this.el.style;
1676 s.opacity = 0.1;
1677 s.filter = "alpha(opacity=10)";
1678 s.display = "";
1679
1680 // var dur = ( navigator.userAgent.match(/msie/gi) ) ? 0.05 : 0.4;
1681 var dur = 0.4;
1682 // var a = new ygAnim_Fade(this.el, dur, 1);
1683 // a.setStart(0.1);
1684 // a.onComplete = function() { tvanim.onComplete(); };
1685
1686 // var a = new YAHOO.util.Anim(this.el, 'opacity', 0.1, 1);
1687 var a = new YAHOO.util.Anim(this.el, {opacity: {from: 0.1, to: 1, unit:""}}, dur);
1688 a.onComplete.subscribe( function() { tvanim.onComplete(); } );
1689 a.animate();
1690 },
1691
1692 /**
1693 * Clean up and invoke callback
1694 */
1695 onComplete: function() {
1696 this.callback();
1697 }
1698};
1699
1700/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1701
1702/**
1703 * A 1/2 second fade out animation.
1704 *
1705 * @constructor
1706 * @param el {HTMLElement} the element to animate
1707 * @param callback {Function} function to invoke when the animation is finished
1708 */
1709YAHOO.widget.TVFadeOut = function(el, callback) {
1710 /**
1711 * The element to animate
1712 * @type HTMLElement
1713 */
1714 this.el = el;
1715
1716 /**
1717 * the callback to invoke when the animation is complete
1718 *
1719 * @type function
1720 */
1721 this.callback = callback;
1722
1723 /**
1724 * @private
1725 */
1726};
1727
1728/**
1729 * Performs the animation
1730 */
1731YAHOO.widget.TVFadeOut.prototype = {
1732 animate: function() {
1733 var tvanim = this;
1734 // var dur = ( navigator.userAgent.match(/msie/gi) ) ? 0.05 : 0.4;
1735 var dur = 0.4;
1736 // var a = new ygAnim_Fade(this.el, dur, 0.1);
1737 // a.onComplete = function() { tvanim.onComplete(); };
1738
1739 // var a = new YAHOO.util.Anim(this.el, 'opacity', 1, 0.1);
1740 var a = new YAHOO.util.Anim(this.el, {opacity: {from: 1, to: 0.1, unit:""}}, dur);
1741 a.onComplete.subscribe( function() { tvanim.onComplete(); } );
1742 a.animate();
1743 },
1744
1745 /**
1746 * Clean up and invoke callback
1747 */
1748 onComplete: function() {
1749 var s = this.el.style;
1750 s.display = "none";
1751 // s.opacity = 1;
1752 s.filter = "alpha(opacity=100)";
1753 this.callback();
1754 }
1755};
1756
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette