📄 treeview.js
字号:
/*Copyright (c) 2008, Yahoo! Inc. All rights reserved.Code licensed under the BSD License:http://developer.yahoo.net/yui/license.txtversion: 2.6.0*/(function () { var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, Lang = YAHOO.lang, Widget = YAHOO.widget;/** * The treeview widget is a generic tree building tool. * @module treeview * @title TreeView Widget * @requires yahoo, event * @optional animation * @namespace YAHOO.widget *//** * Contains the tree view state data and the root node. * * @class TreeView * @uses YAHOO.util.EventProvider * @constructor * @param {string|HTMLElement} id The id of the element, or the element itself that the tree will be inserted into. Existing markup in this element, if valid, will be used to build the tree * @param {Array|object|string} oConfig (optional) An array containing the definition of the tree. Objects will be converted to arrays of one element. A string will produce a single TextNode * */YAHOO.widget.TreeView = function(id, oConfig) { if (id) { this.init(id); } if (oConfig) { if (!Lang.isArray(oConfig)) { oConfig = [oConfig]; } this.buildTreeFromObject(oConfig); } else if (Lang.trim(this._el.innerHTML)) { this.buildTreeFromMarkup(id); }};var TV = Widget.TreeView;TV.prototype = { /** * The id of tree container element * @property id * @type String */ id: null, /** * The host element for this tree * @property _el * @private * @type HTMLelement */ _el: null, /** * Flat collection of all nodes in this tree. This is a sparse * array, so the length property can't be relied upon for a * node count for the tree. * @property _nodes * @type Node[] * @private */ _nodes: null, /** * We lock the tree control while waiting for the dynamic loader to return * @property locked * @type boolean */ locked: false, /** * The animation to use for expanding children, if any * @property _expandAnim * @type string * @private */ _expandAnim: null, /** * The animation to use for collapsing children, if any * @property _collapseAnim * @type string * @private */ _collapseAnim: null, /** * The current number of animations that are executing * @property _animCount * @type int * @private */ _animCount: 0, /** * The maximum number of animations to run at one time. * @property maxAnim * @type int */ maxAnim: 2, /** * Whether there is any subscriber to dblClickEvent * @property _hasDblClickSubscriber * @type boolean * @private */ _hasDblClickSubscriber: false, /** * Stores the timer used to check for double clicks * @property _dblClickTimer * @type window.timer object * @private */ _dblClickTimer: null, /** * Sets up the animation for expanding children * @method setExpandAnim * @param {string} type the type of animation (acceptable values defined * in YAHOO.widget.TVAnim) */ setExpandAnim: function(type) { this._expandAnim = (Widget.TVAnim.isValid(type)) ? type : null; }, /** * Sets up the animation for collapsing children * @method setCollapseAnim * @param {string} the type of animation (acceptable values defined in * YAHOO.widget.TVAnim) */ setCollapseAnim: function(type) { this._collapseAnim = (Widget.TVAnim.isValid(type)) ? type : null; }, /** * Perform the expand animation if configured, or just show the * element if not configured or too many animations are in progress * @method animateExpand * @param el {HTMLElement} the element to animate * @param node {YAHOO.util.Node} the node that was expanded * @return {boolean} true if animation could be invoked, false otherwise */ animateExpand: function(el, node) { if (this._expandAnim && this._animCount < this.maxAnim) { // this.locked = true; var tree = this; var a = Widget.TVAnim.getAnim(this._expandAnim, el, function() { tree.expandComplete(node); }); if (a) { ++this._animCount; this.fireEvent("animStart", { "node": node, "type": "expand" }); a.animate(); } return true; } return false; }, /** * Perform the collapse animation if configured, or just show the * element if not configured or too many animations are in progress * @method animateCollapse * @param el {HTMLElement} the element to animate * @param node {YAHOO.util.Node} the node that was expanded * @return {boolean} true if animation could be invoked, false otherwise */ animateCollapse: function(el, node) { if (this._collapseAnim && this._animCount < this.maxAnim) { // this.locked = true; var tree = this; var a = Widget.TVAnim.getAnim(this._collapseAnim, el, function() { tree.collapseComplete(node); }); if (a) { ++this._animCount; this.fireEvent("animStart", { "node": node, "type": "collapse" }); a.animate(); } return true; } return false; }, /** * Function executed when the expand animation completes * @method expandComplete */ expandComplete: function(node) { --this._animCount; this.fireEvent("animComplete", { "node": node, "type": "expand" }); // this.locked = false; }, /** * Function executed when the collapse animation completes * @method collapseComplete */ collapseComplete: function(node) { --this._animCount; this.fireEvent("animComplete", { "node": node, "type": "collapse" }); // this.locked = false; }, /** * Initializes the tree * @method init * @parm {string|HTMLElement} id the id of the element that will hold the tree * @private */ init: function(id) { this._el = Dom.get(id); this.id = Dom.generateId(this._el,"yui-tv-auto-id-"); /** * When animation is enabled, this event fires when the animation * starts * @event animStart * @type CustomEvent * @param {YAHOO.widget.Node} node the node that is expanding/collapsing * @parm {String} type the type of animation ("expand" or "collapse") */ this.createEvent("animStart", this); /** * When animation is enabled, this event fires when the animation * completes * @event animComplete * @type CustomEvent * @param {YAHOO.widget.Node} node the node that is expanding/collapsing * @parm {String} type the type of animation ("expand" or "collapse") */ this.createEvent("animComplete", this); /** * Fires when a node is going to be collapsed. Return false to stop * the collapse. * @event collapse * @type CustomEvent * @param {YAHOO.widget.Node} node the node that is collapsing */ this.createEvent("collapse", this); /** * Fires after a node is successfully collapsed. This event will not fire * if the "collapse" event was cancelled. * @event collapseComplete * @type CustomEvent * @param {YAHOO.widget.Node} node the node that was collapsed */ this.createEvent("collapseComplete", this); /** * Fires when a node is going to be expanded. Return false to stop * the collapse. * @event expand * @type CustomEvent * @param {YAHOO.widget.Node} node the node that is expanding */ this.createEvent("expand", this); /** * Fires after a node is successfully expanded. This event will not fire * if the "expand" event was cancelled. * @event expandComplete * @type CustomEvent * @param {YAHOO.widget.Node} node the node that was expanded */ this.createEvent("expandComplete", this); /** * Fires when the Enter key is pressed on a node that has the focus * @event enterKeyPressed * @type CustomEvent * @param {YAHOO.widget.Node} node the node that has the focus */ this.createEvent("enterKeyPressed", this); /** * Fires when the label in a TextNode or MenuNode or content in an HTMLNode receives a Click. * The listener may return false to cancel toggling and focusing on the node. * @event clickEvent * @type CustomEvent * @param oArgs.event {HTMLEvent} The event object * @param oArgs.node {YAHOO.widget.Node} node the node that was clicked */ this.createEvent("clickEvent", this); /** * Fires when the label in a TextNode or MenuNode or content in an HTMLNode receives a double Click * @event dblClickEvent * @type CustomEvent * @param oArgs.event {HTMLEvent} The event object * @param oArgs.node {YAHOO.widget.Node} node the node that was clicked */ var self = this; this.createEvent("dblClickEvent", { scope:this, onSubscribeCallback: function() { self._hasDblClickSubscriber = true; } }); /** * Custom event that is fired when the text node label is clicked. * The node clicked is provided as an argument * * @event labelClick * @type CustomEvent * @param {YAHOO.widget.Node} node the node clicked * @deprecated use clickEvent or dblClickEvent */ this.createEvent("labelClick", this); this._nodes = []; // store a global reference TV.trees[this.id] = this; // Set up the root node this.root = new Widget.RootNode(this); var LW = Widget.LogWriter; // YAHOO.util.Event.onContentReady(this.id, this.handleAvailable, this, true); // YAHOO.util.Event.on(this.id, "click", this.handleClick, this, true); }, //handleAvailable: function() { //var Event = YAHOO.util.Event; //Event.on(this.id, //}, /** * Builds the TreeView from an object. This is the method called by the constructor to build the tree when it has a second argument. * @method buildTreeFromObject * @param oConfig {Array} array containing a full description of the tree * */ buildTreeFromObject: function (oConfig) { var build = function (parent, oConfig) { var i, item, node, children, type, NodeType, ThisType; for (i = 0; i < oConfig.length; i++) { item = oConfig[i]; if (Lang.isString(item)) { node = new Widget.TextNode(item, parent); } else if (Lang.isObject(item)) { children = item.children; delete item.children; type = item.type || 'text'; delete item.type; switch (type.toLowerCase()) { case 'text': node = new Widget.TextNode(item, parent); break; case 'menu': node = new Widget.MenuNode(item, parent); break; case 'html': node = new Widget.HTMLNode(item, parent); break; default: NodeType = Widget[type]; if (Lang.isObject(NodeType)) { for (ThisType = NodeType; ThisType && ThisType !== Widget.Node; ThisType = ThisType.superclass.constructor) {} if (ThisType) { node = new NodeType(item, parent); } else { } } else { } } if (children) { build(node,children); } } else { } } }; build(this.root,oConfig); },/** * Builds the TreeView from existing markup. Markup should consist of <UL> or <OL> elements, possibly nested. * Depending what the <LI> elements contain the following will be created: <ul> * <li>plain text: a regular TextNode</li> * <li>an (un-)ordered list: a nested branch</li> * <li>anything else: an HTMLNode</li></ul> * Only the first outermost (un-)ordered list in the markup and its children will be parsed. * Tree will be fully collapsed. * HTMLNodes have hasIcon set to true if the markup for that node has a className called hasIcon. * @method buildTreeFromMarkup * @param {string|HTMLElement} id the id of the element that contains the markup or a reference to it. */ buildTreeFromMarkup: function (id) { var build = function (parent,markup) { var el, node, child, text; for (el = Dom.getFirstChild(markup); el; el = Dom.getNextSibling(el)) { if (el.nodeType == 1) { switch (el.tagName.toUpperCase()) { case 'LI': for (child = el.firstChild; child; child = child.nextSibling) { if (child.nodeType == 3) { text = Lang.trim(child.nodeValue); if (text.length) { node = new Widget.TextNode(text, parent, false); } } else { switch (child.tagName.toUpperCase()) { case 'UL': case 'OL': build(node,child); break; case 'A': node = new Widget.TextNode({ label:child.innerHTML, href: child.href, target:child.target, title:child.title ||child.alt },parent,false); break; default: node = new Widget.HTMLNode(child.parentNode.innerHTML, parent, false, true); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -