[Gd-chatter] r10947 - in trunk/documentation/topic/cms: css js

housel at gwydiondylan.org housel at gwydiondylan.org
Wed Nov 8 07:00:17 CET 2006


Author: housel
Date: Wed Nov  8 07:00:14 2006
New Revision: 10947

Modified:
   trunk/documentation/topic/cms/css/tree.css
   trunk/documentation/topic/cms/js/event.js
   trunk/documentation/topic/cms/js/treeview.js
   trunk/documentation/topic/cms/js/yahoo.js
Log:
Bug: 7249
Update the treeview control from version 0.11.4 of the Yahoo! User
Interface Library.


Modified: trunk/documentation/topic/cms/css/tree.css
==============================================================================
--- trunk/documentation/topic/cms/css/tree.css	(original)
+++ trunk/documentation/topic/cms/css/tree.css	Wed Nov  8 07:00:14 2006
@@ -1,4 +1,9 @@
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.txt
+Version: 0.11.3
+*/
 
 /* first or middle sibling, no children */
 .ygtvtn {

Modified: trunk/documentation/topic/cms/js/event.js
==============================================================================
--- trunk/documentation/topic/cms/js/event.js	(original)
+++ trunk/documentation/topic/cms/js/event.js	Wed Nov  8 07:00:14 2006
@@ -1,62 +1,97 @@
-/*                                                                                                                                                      
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    
-Code licensed under the BSD License:                                                                                                                    
-http://developer.yahoo.net/yui/license.txt                                                                                                              
-version: 0.10.0                                                                                                                                         
-*/ 
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+Version: 0.11.4
+*/
 
 /**
  * The CustomEvent class lets you define events for your application
  * that can be subscribed to by one or more independent component.
  *
- * @param {String} type The type of event, which is passed to the callback
- *                 when the event fires
- * @param {Object} oScope The context the event will fire from.  "this" will
- *                 refer to this object in the callback.  Default value: 
- *                 the window object.  The listener can override this.
+ * @param {String}  type The type of event, which is passed to the callback
+ *                  when the event fires
+ * @param {Object}  oScope The context the event will fire from.  "this" will
+ *                  refer to this object in the callback.  Default value:
+ *                  the window object.  The listener can override this.
+ * @param {boolean} silent pass true to prevent the event from writing to
+ *                  the log system
+ * @namespace YAHOO.util
+ * @class CustomEvent
  * @constructor
  */
-YAHOO.util.CustomEvent = function(type, oScope) {
+YAHOO.util.CustomEvent = function(type, oScope, silent) {
+
     /**
      * The type of event, returned to subscribers when the event fires
+     * @property type
      * @type string
      */
     this.type = type;
 
     /**
-     * The scope the the event will fire from by default.  Defaults to the window 
+     * The scope the the event will fire from by default.  Defaults to the window
      * obj
+     * @property scope
      * @type object
      */
     this.scope = oScope || window;
 
     /**
+     * By default all custom events are logged in the debug build, set silent
+     * to true to disable logging for this event.
+     * @property silent
+     * @type boolean
+     */
+    this.silent = silent;
+
+    /**
      * The subscribers to this event
+     * @property subscribers
      * @type Subscriber[]
      */
     this.subscribers = [];
 
-    // Register with the event utility for automatic cleanup.  Made optional
-    // so that CustomEvent can be used independently of pe.event
-    if (YAHOO.util.Event) { 
-        YAHOO.util.Event.regCE(this);
+    if (!this.silent) {
     }
+
+    // Only add subscribe events for events that are not generated by CustomEvent
+    //if (oScope && (oScope.constructor != this.constructor)) {
+
+        /*
+         * Custom events provide a custom event that fires whenever there is
+         * a new subscriber to the event.  This provides an opportunity to
+         * handle the case where there is a non-repeating event that has
+         * already fired has a new subscriber.
+         *
+         * type CustomEvent
+         */
+        //this.subscribeEvent =
+                //new YAHOO.util.CustomEvent("subscribe", this, true);
+
+    //}
 };
 
 YAHOO.util.CustomEvent.prototype = {
     /**
      * Subscribes the caller to this event
+     * @method subscribe
      * @param {Function} fn       The function to execute
      * @param {Object}   obj      An object to be passed along when the event fires
      * @param {boolean}  bOverride If true, the obj passed in becomes the execution
      *                            scope of the listener
      */
     subscribe: function(fn, obj, bOverride) {
+        //if (this.subscribeEvent) {
+            //this.subscribeEvent.fire(fn, obj, bOverride);
+        //}
+
         this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );
     },
 
     /**
      * Unsubscribes the caller from this event
+     * @method unsubscribe
      * @param {Function} fn  The function to execute
      * @param {Object}   obj An object to be passed along when the event fires
      * @return {boolean} True if the subscriber was found and detached.
@@ -83,29 +118,47 @@
      *   - All of the arguments fire() was executed with as an array
      *   - The custom object (if any) that was passed into the subscribe() method
      *   </pre>
-     *   
+     * @method fire
      * @param {Array} an arbitrary set of parameters to pass to the handler
      */
     fire: function() {
-        for (var i=0, len=this.subscribers.length; i<len; ++i) {
+        var len=this.subscribers.length;
+        if (!len && this.silent) {
+            return;
+        }
+
+        var args = [];
+
+        for (var i=0; i<arguments.length; ++i) {
+            args.push(arguments[i]);
+        }
+
+        if (!this.silent) {
+        }
+
+        for (i=0; i<len; ++i) {
             var s = this.subscribers[i];
             if (s) {
+                if (!this.silent) {
+                }
                 var scope = (s.override) ? s.obj : this.scope;
-                s.fn.call(scope, this.type, arguments, s.obj);
+                s.fn.call(scope, this.type, args, s.obj);
             }
         }
     },
 
     /**
      * Removes all listeners
+     * @method unsubscribeAll
      */
     unsubscribeAll: function() {
         for (var i=0, len=this.subscribers.length; i<len; ++i) {
-            this._delete(i);
+            this._delete(len - 1 - i);
         }
     },
 
     /**
+     * @method _delete
      * @private
      */
     _delete: function(index) {
@@ -115,23 +168,36 @@
             delete s.obj;
         }
 
-        delete this.subscribers[index];
+        // delete this.subscribers[index];
+        this.subscribers.splice(index, 1);
+    },
+
+    /**
+     * @method toString
+     */
+    toString: function() {
+         return "CustomEvent: " + "'" + this.type  + "', " +
+             "scope: " + this.scope;
+
     }
 };
 
 /////////////////////////////////////////////////////////////////////
 
 /**
- * @class Stores the subscriber information to be used when the event fires.
+ * Stores the subscriber information to be used when the event fires.
  * @param {Function} fn       The function to execute
  * @param {Object}   obj      An object to be passed along when the event fires
  * @param {boolean}  bOverride If true, the obj passed in becomes the execution
  *                            scope of the listener
+ * @class Subscriber
  * @constructor
  */
 YAHOO.util.Subscriber = function(fn, obj, bOverride) {
+
     /**
      * The callback that will be execute when the event fires
+     * @property fn
      * @type function
      */
     this.fn = fn;
@@ -139,6 +205,7 @@
     /**
      * An optional custom object that will passed to the callback when
      * the event fires
+     * @property obj
      * @type object
      */
     this.obj = obj || null;
@@ -148,6 +215,7 @@
      * event is created (usually the object which contains the event).
      * By setting override to true, the execution scope becomes the custom
      * object passed in by the subscriber
+     * @property override
      * @type boolean
      */
     this.override = (bOverride);
@@ -157,32 +225,39 @@
  * Returns true if the fn and obj match this objects properties.
  * Used by the unsubscribe method to match the right subscriber.
  *
+ * @method contains
  * @param {Function} fn the function to execute
  * @param {Object} obj an object to be passed along when the event fires
- * @return {boolean} true if the supplied arguments match this 
+ * @return {boolean} true if the supplied arguments match this
  *                   subscriber's signature.
  */
 YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
     return (this.fn == fn && this.obj == obj);
 };
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+/**
+ * @method toString
+ */
+YAHOO.util.Subscriber.prototype.toString = function() {
+    return "Subscriber { obj: " + (this.obj || "")  +
+           ", override: " +  (this.override || "no") + " }";
+};
 
-// Only load this library once.  If it is loaded a second time, existing
-// events cannot be detached.
+// The first instance of Event will win if it is loaded more than once.
 if (!YAHOO.util.Event) {
 
 /**
- * @class
  * The event utility provides functions to add and remove event listeners,
  * event cleansing.  It also tries to automatically remove listeners it
  * registers during the unload event.
- * @constructor
+ * @namespace YAHOO.util
+ * @class Event
  */
     YAHOO.util.Event = function() {
 
         /**
          * True after the onload event has fired
+         * @property loadComplete
          * @type boolean
          * @private
          */
@@ -190,6 +265,7 @@
 
         /**
          * Cache of wrapped listeners
+         * @property listeners
          * @type array
          * @private
          */
@@ -197,6 +273,7 @@
 
         /**
          * Listeners that will be attached during the onload event
+         * @property delayedListeners
          * @type array
          * @private
          */
@@ -205,28 +282,23 @@
         /**
          * User-defined unload function that will be fired before all events
          * are detached
+         * @property unloadListeners
          * @type array
          * @private
          */
         var unloadListeners = [];
 
         /**
-         * Cache of the custom events that have been defined.  Used for
-         * automatic cleanup
-         * @type array
-         * @private
-         */
-        var customEvents = [];
-
-        /**
          * Cache of DOM0 event handlers to work around issues with DOM2 events
          * in Safari
+         * @property legacyEvents
          * @private
          */
         var legacyEvents = [];
 
         /**
          * Listener stack for DOM0 events
+         * @property legacyHandlers
          * @private
          */
         var legacyHandlers = [];
@@ -235,24 +307,28 @@
          * The number of times to poll after window.onload.  This number is
          * increased if additional late-bound handlers are requested after
          * the page load.
+         * @property retryCount
          * @private
          */
         var retryCount = 0;
 
         /**
          * onAvailable listeners
+         * @property onAvailStack
          * @private
          */
         var onAvailStack = [];
 
         /**
          * Lookup table for legacy events
+         * @property legacyMap
          * @private
          */
         var legacyMap = [];
 
         /**
          * Counter for auto id generation
+         * @property counter
          * @private
          */
         var counter = 0;
@@ -262,46 +338,53 @@
             /**
              * The number of times we should look for elements that are not
              * in the DOM at the time the event is requested after the document
-             * has been loaded.  The default is 200 at 50 ms, so it will poll
+             * has been loaded.  The default is 200 at amp;50 ms, so it will poll
              * for 10 seconds or until all outstanding handlers are bound
              * (whichever comes first).
+             * @property POLL_RETRYS
              * @type int
              */
             POLL_RETRYS: 200,
 
             /**
              * The poll interval in milliseconds
+             * @property POLL_INTERVAL
              * @type int
              */
             POLL_INTERVAL: 50,
 
             /**
              * Element to bind, int constant
+             * @property EL
              * @type int
              */
             EL: 0,
 
             /**
              * Type of event, int constant
+             * @property TYPE
              * @type int
              */
             TYPE: 1,
 
             /**
              * Function to execute, int constant
+             * @property FN
              * @type int
              */
             FN: 2,
 
             /**
              * Function wrapped for scope correction and cleanup, int constant
+             * @property WFN
              * @type int
              */
             WFN: 3,
 
             /**
-             * Object passed in by the user that will be returned as a 
+             * Object passed in by the user that will be returned as a
              * parameter to the callback, int constant
+             * @property SCOPE
              * @type int
              */
             SCOPE: 3,
@@ -309,29 +392,33 @@
             /**
              * Adjusted scope, either the element we are registering the event
              * on or the custom object passed in by the listener, int constant
+             * @property ADJ_SCOPE
              * @type int
              */
             ADJ_SCOPE: 4,
 
             /**
              * Safari detection is necessary to work around the preventDefault
-             * bug that makes it so you can't cancel a href click from the 
+             * bug that makes it so you can't cancel a href click from the
              * handler.  There is not a capabilities check we can use here.
+             * @property isSafari
              * @private
              */
             isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),
 
             /**
-             * IE detection needed to properly calculate pageX and pageY.  
-             * capabilities checking didn't seem to work because another 
-             * browser that does not provide the properties have the values 
+             * IE detection needed to properly calculate pageX and pageY.
+             * capabilities checking didn't seem to work because another
+             * browser that does not provide the properties have the values
              * calculated in a different manner than IE.
+             * @property isIE
              * @private
              */
-            isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && 
+            isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) &&
                     navigator.userAgent.match(/msie/gi)),
 
             /**
+             * @method addDelayedListener
              * @private
              */
             addDelayedListener: function(el, sType, fn, oScope, bOverride) {
@@ -349,6 +436,7 @@
             },
 
             /**
+             * @method startTimeout
              * @private
              */
             startTimeout: function(interval) {
@@ -365,18 +453,21 @@
              * initial page load it will poll for a fixed time for the element.
              * The number of times it will poll and the frequency are
              * configurable.  By default it will poll for 10 seconds.
-             * @param {string} p_id the id of the element to look for.
+             *
+             * @method onAvailable
+             *
+             * @param {string}   p_id the id of the element to look for.
              * @param {function} p_fn what to execute when the element is found.
-             * @param {object} p_obj an optional object to be passed back as
-             * a parameter to p_fn.
-             * @param {boolean} p_override If set to true, p_fn will execute
-             * in the scope of p_obj
+             * @param {object}   p_obj an optional object to be passed back as
+             *                   a parameter to p_fn.
+             * @param {boolean}  p_override If set to true, p_fn will execute
+             *                   in the scope of p_obj
              *
              */
             onAvailable: function(p_id, p_fn, p_obj, p_override) {
-                onAvailStack.push( { id:       p_id, 
-                                     fn:       p_fn, 
-                                     obj:      p_obj, 
+                onAvailStack.push( { id:       p_id,
+                                     fn:       p_fn,
+                                     obj:      p_obj,
                                      override: p_override } );
 
                 retryCount = this.POLL_RETRYS;
@@ -387,16 +478,18 @@
             /**
              * Appends an event handler
              *
-             * @param {Object}   el        The html element to assign the 
+             * @method addListener
+             *
+             * @param {Object}   el        The html element to assign the
              *                             event to
              * @param {String}   sType     The type of event to append
              * @param {Function} fn        The method the event invokes
-             * @param {Object}   oScope    An arbitrary object that will be 
+             * @param {Object}   oScope    An arbitrary object that will be
              *                             passed as a parameter to the handler
              * @param {boolean}  bOverride If true, the obj passed in becomes
              *                             the execution scope of the listener
              * @return {boolean} True if the action was successful or defered,
-             *                        false if one or more of the elements 
+             *                        false if one or more of the elements
              *                        could not have the event bound to it.
              */
             addListener: function(el, sType, fn, oScope, bOverride) {
@@ -409,45 +502,45 @@
                 if ( this._isValidCollection(el)) {
                     var ok = true;
                     for (var i=0,len=el.length; i<len; ++i) {
-                        ok = ( this.on(el[i], 
-                                       sType, 
-                                       fn, 
-                                       oScope, 
+                        ok = ( this.on(el[i],
+                                       sType,
+                                       fn,
+                                       oScope,
                                        bOverride) && ok );
                     }
                     return ok;
 
                 } else if (typeof el == "string") {
                     var oEl = this.getEl(el);
-                    // If the el argument is a string, we assume it is 
+                    // If the el argument is a string, we assume it is
                     // actually the id of the element.  If the page is loaded
-                    // we convert el to the actual element, otherwise we 
+                    // we convert el to the actual element, otherwise we
                     // defer attaching the event until onload event fires
 
-                    // check to see if we need to delay hooking up the event 
+                    // check to see if we need to delay hooking up the event
                     // until after the page loads.
                     if (loadComplete && oEl) {
                         el = oEl;
                     } else {
                         // defer adding the event until onload fires
-                        this.addDelayedListener(el, 
-                                                sType, 
-                                                fn, 
-                                                oScope, 
+                        this.addDelayedListener(el,
+                                                sType,
+                                                fn,
+                                                oScope,
                                                 bOverride);
 
                         return true;
                     }
                 }
 
-                // Element should be an html element or an array if we get 
+                // Element should be an html element or an array if we get
                 // here.
                 if (!el) {
                     return false;
                 }
 
-                // we need to make sure we fire registered unload events 
-                // prior to automatically unhooking them.  So we hang on to 
+                // we need to make sure we fire registered unload events
+                // prior to automatically unhooking them.  So we hang on to
                 // these instead of attaching them to the window and fire the
                 // handles explicitly during our one unload event.
                 if ("unload" == sType && oScope !== this) {
@@ -456,7 +549,6 @@
                     return true;
                 }
 
-
                 // if the user chooses to override the scope, we use the custom
                 // object passed in, otherwise the executing scope will be the
                 // HTML element that the event is registered on
@@ -465,7 +557,7 @@
                 // wrap the function so we can return the oScope object when
                 // the event fires;
                 var wrappedFn = function(e) {
-                        return fn.call(scope, YAHOO.util.Event.getEvent(e), 
+                        return fn.call(scope, YAHOO.util.Event.getEvent(e),
                                 oScope);
                     };
 
@@ -476,18 +568,22 @@
 
                 if (this.useLegacyEvent(el, sType)) {
                     var legacyIndex = this.getLegacyIndex(el, sType);
-                    if (legacyIndex == -1) {
+
+                    // Add a new dom0 wrapper if one is not detected for this
+                    // element
+                    if ( legacyIndex == -1 ||
+                                el != legacyEvents[legacyIndex][0] ) {
 
                         legacyIndex = legacyEvents.length;
                         legacyMap[el.id + sType] = legacyIndex;
 
-                        // cache the signature for the DOM0 event, and 
+                        // cache the signature for the DOM0 event, and
                         // include the existing handler for the event, if any
-                        legacyEvents[legacyIndex] = 
+                        legacyEvents[legacyIndex] =
                             [el, sType, el["on" + sType]];
                         legacyHandlers[legacyIndex] = [];
 
-                        el["on" + sType] = 
+                        el["on" + sType] =
                             function(e) {
                                 YAHOO.util.Event.fireLegacyEvent(
                                     YAHOO.util.Event.getEvent(e), legacyIndex);
@@ -496,29 +592,25 @@
 
                     // add a reference to the wrapped listener to our custom
                     // stack of events
-                    legacyHandlers[legacyIndex].push(index);
+                    //legacyHandlers[legacyIndex].push(index);
+                    legacyHandlers[legacyIndex].push(li);
 
                 // DOM2 Event model
                 } else if (el.addEventListener) {
                     el.addEventListener(sType, wrappedFn, false);
-                // Internet Explorer abstraction
+                // IE
                 } else if (el.attachEvent) {
                     el.attachEvent("on" + sType, wrappedFn);
                 }
 
                 return true;
-                
-            },
 
-            /**
-             * Shorthand for YAHOO.util.Event.addListener
-             * @type function
-             */
-            // on: this.addListener,
+            },
 
             /**
              * When using legacy events, the handler is routed to this object
              * so we can fire our custom listener stack.
+             * @method fireLegacyEvent
              * @private
              */
             fireLegacyEvent: function(e, legacyIndex) {
@@ -526,18 +618,11 @@
 
                 var le = legacyHandlers[legacyIndex];
                 for (var i=0,len=le.length; i<len; ++i) {
-                    var index = le[i];
-                    if (index) {
-                        var li = listeners[index];
-                        if ( li && li[this.WFN] ) {
-                            var scope = li[this.ADJ_SCOPE];
-                            var ret = li[this.WFN].call(scope, e);
-                            ok = (ok && ret);
-                        } else {
-                            // This listener was removed, so delete it from
-                            // the array
-                            delete le[i];
-                        }
+                    var li = le[i];
+                    if ( li && li[this.WFN] ) {
+                        var scope = li[this.ADJ_SCOPE];
+                        var ret = li[this.WFN].call(scope, e);
+                        ok = (ok && ret);
                     }
                 }
 
@@ -545,37 +630,27 @@
             },
 
             /**
-             * Returns the legacy event index that matches the supplied 
+             * Returns the legacy event index that matches the supplied
              * signature
+             * @method getLegacyIndex
              * @private
              */
             getLegacyIndex: function(el, sType) {
-                /*
-                for (var i=0,len=legacyEvents.length; i<len; ++i) {
-                    var le = legacyEvents[i];
-                    if (le && le[0] === el && le[1] === sType) {
-                        return i;
-                    }
-                }
-                return -1;
-                */
-
                 var key = this.generateId(el) + sType;
-                if (typeof legacyMap[key] == "undefined") { 
+                if (typeof legacyMap[key] == "undefined") {
                     return -1;
                 } else {
                     return legacyMap[key];
                 }
-
             },
 
             /**
              * Logic that determines when we should automatically use legacy
              * events instead of DOM2 events.
+             * @method useLegacyEvent
              * @private
              */
             useLegacyEvent: function(el, sType) {
-
                 if (!el.addEventListener && !el.attachEvent) {
                     return true;
                 } else if (this.isSafari) {
@@ -583,18 +658,19 @@
                         return true;
                     }
                 }
-
                 return false;
             },
-                    
+
             /**
              * Removes an event handler
              *
-             * @param {Object} el the html element or the id of the element to 
+             * @method removeListener
+             *
+             * @param {Object} el the html element or the id of the element to
              * assign the event to.
              * @param {String} sType the type of event to remove
              * @param {Function} fn the method the event invokes
-             * @return {boolean} true if the unbind was successful, false 
+             * @return {boolean} true if the unbind was successful, false
              * otherwise
              */
             removeListener: function(el, sType, fn, index) {
@@ -603,13 +679,15 @@
                     return false;
                 }
 
+                var i, len;
+
                 // The el argument can be a string
                 if (typeof el == "string") {
                     el = this.getEl(el);
                 // The el argument can be an array of elements or element ids.
                 } else if ( this._isValidCollection(el)) {
                     var ok = true;
-                    for (var i=0,len=el.length; i<len; ++i) {
+                    for (i=0,len=el.length; i<len; ++i) {
                         ok = ( this.removeListener(el[i], sType, fn) && ok );
                     }
                     return ok;
@@ -619,11 +697,11 @@
 
                     for (i=0, len=unloadListeners.length; i<len; i++) {
                         var li = unloadListeners[i];
-                        if (li && 
-                            li[0] == el && 
-                            li[1] == sType && 
+                        if (li &&
+                            li[0] == el &&
+                            li[1] == sType &&
                             li[2] == fn) {
-                                delete unloadListeners[i];
+                                unloadListeners.splice(i, 1);
                                 return true;
                         }
                     }
@@ -632,7 +710,9 @@
                 }
 
                 var cacheItem = null;
-  
+
+                //var index = arguments[3];
+
                 if ("undefined" == typeof index) {
                     index = this._getCacheIndex(el, sType, fn);
                 }
@@ -645,8 +725,22 @@
                     return false;
                 }
 
+                if (this.useLegacyEvent(el, sType)) {
+                    var legacyIndex = this.getLegacyIndex(el, sType);
+                    var llist = legacyHandlers[legacyIndex];
+                    if (llist) {
+                        for (i=0, len=llist.length; i<len; ++i) {
+                            li = llist[i];
+                            if (li &&
+                                li[this.EL] == el &&
+                                li[this.TYPE] == sType &&
+                                li[this.FN] == fn) {
+                                    llist.splice(i, 1);
+                            }
+                        }
+                    }
 
-                if (el.removeEventListener) {
+                } else if (el.removeEventListener) {
                     el.removeEventListener(sType, cacheItem[this.WFN], false);
                 } else if (el.detachEvent) {
                     el.detachEvent("on" + sType, cacheItem[this.WFN]);
@@ -655,7 +749,7 @@
                 // removed the wrapped handler
                 delete listeners[index][this.WFN];
                 delete listeners[index][this.FN];
-                delete listeners[index];
+                listeners.splice(index, 1);
 
                 return true;
 
@@ -663,24 +757,39 @@
 
             /**
              * Returns the event's target element
+             * @method getTarget
              * @param {Event} ev the event
              * @param {boolean} resolveTextNode when set to true the target's
-             *                  parent will be returned if the target is a 
-             *                  text node
+             *                  parent will be returned if the target is a
+             *                  text node.  @deprecated, the text node is
+             *                  now resolved automatically
              * @return {HTMLElement} the event's target
              */
             getTarget: function(ev, resolveTextNode) {
                 var t = ev.target || ev.srcElement;
+                return this.resolveTextNode(t);
+            },
 
-                if (resolveTextNode && t && "#text" == t.nodeName) {
-                    return t.parentNode;
+            /**
+             * In some cases, some browsers will return a text node inside
+             * the actual element that was targeted.  This normalizes the
+             * return value for getTarget and getRelatedTarget.
+             * @method resolveTextNode
+             * @param {HTMLElement} node to resolve
+             * @return  the normized node
+             */
+            resolveTextNode: function(node) {
+                if (node && node.nodeName &&
+                        "#TEXT" == node.nodeName.toUpperCase()) {
+                    return node.parentNode;
                 } else {
-                    return t;
+                    return node;
                 }
             },
 
             /**
              * Returns the event's pageX
+             * @method getPageX
              * @param {Event} ev the event
              * @return {int} the event's pageX
              */
@@ -699,6 +808,7 @@
 
             /**
              * Returns the event's pageY
+             * @method getPageY
              * @param {Event} ev the event
              * @return {int} the event's pageY
              */
@@ -717,6 +827,7 @@
 
             /**
              * Returns the pageX and pageY properties as an indexed array.
+             * @method getXY
              * @type int[]
              */
             getXY: function(ev) {
@@ -724,7 +835,8 @@
             },
 
             /**
-             * Returns the event's related target 
+             * Returns the event's related target
+             * @method getRelatedTarget
              * @param {Event} ev the event
              * @return {HTMLElement} the event's relatedTarget
              */
@@ -738,12 +850,13 @@
                     }
                 }
 
-                return t;
+                return this.resolveTextNode(t);
             },
 
             /**
              * Returns the time of the event.  If the time is not included, the
              * event is modified using the current time.
+             * @method getTime
              * @param {Event} ev the event
              * @return {Date} the time of the event
              */
@@ -752,8 +865,8 @@
                     var t = new Date().getTime();
                     try {
                         ev.time = t;
-                    } catch(e) { 
-                        // can't set the time property  
+                    } catch(e) {
+                        // can't set the time property
                         return t;
                     }
                 }
@@ -763,6 +876,7 @@
 
             /**
              * Convenience method for stopPropagation + preventDefault
+             * @method stopEvent
              * @param {Event} ev the event
              */
             stopEvent: function(ev) {
@@ -772,6 +886,7 @@
 
             /**
              * Stops event propagation
+             * @method stopPropagation
              * @param {Event} ev the event
              */
             stopPropagation: function(ev) {
@@ -784,6 +899,7 @@
 
             /**
              * Prevents the default behavior of the event
+             * @method preventDefault
              * @param {Event} ev the event
              */
             preventDefault: function(ev) {
@@ -793,15 +909,16 @@
                     ev.returnValue = false;
                 }
             },
-             
+
             /**
              * Finds the event in the window object, the caller's arguments, or
              * in the arguments of another method in the callstack.  This is
              * executed automatically for events registered through the event
              * manager, so the implementer should not normally need to execute
              * this function at all.
+             * @method getEvent
              * @param {Event} the event parameter from the handler
-             * @return {Event} the event 
+             * @return {Event} the event
              */
             getEvent: function(e) {
                 var ev = e || window.event;
@@ -822,6 +939,7 @@
 
             /**
              * Returns the charcode for an event
+             * @method getCharCode
              * @param {Event} ev the event
              * @return {int} the event's charCode
              */
@@ -830,15 +948,17 @@
             },
 
             /**
-             * @private
              * Locating the saved event handler data by function ref
+             *
+             * @method _getCacheIndex
+             * @private
              */
             _getCacheIndex: function(el, sType, fn) {
                 for (var i=0,len=listeners.length; i<len; ++i) {
                     var li = listeners[i];
-                    if ( li                 && 
-                         li[this.FN] == fn  && 
-                         li[this.EL] == el  && 
+                    if ( li                 &&
+                         li[this.FN] == fn  &&
+                         li[this.EL] == el  &&
                          li[this.TYPE] == sType ) {
                         return i;
                     }
@@ -848,8 +968,9 @@
             },
 
             /**
-             * Generates an unique ID for the element if it does not already 
+             * Generates an unique ID for the element if it does not already
              * have one.
+             * @method generateId
              * @param el the element
              * @return {string} the id of the element
              */
@@ -857,7 +978,8 @@
                 var id = el.id;
 
                 if (!id) {
-                    id = "yuievtautoid-" + (counter++);
+                    id = "yuievtautoid-" + counter;
+                    ++counter;
                     el.id = id;
                 }
 
@@ -866,10 +988,11 @@
 
             /**
              * We want to be able to use getElementsByTagName as a collection
-             * to attach a group of events to.  Unfortunately, different 
+             * to attach a group of events to.  Unfortunately, different
              * browsers return different types of collections.  This function
-             * tests to determine if the object is array-like.  It will also 
+             * tests to determine if the object is array-like.  It will also
              * fail if the object is an array, but is empty.
+             * @method _isValidCollection
              * @param o the object to test
              * @return {boolean} true if the object is array-like and populated
              * @private
@@ -887,13 +1010,15 @@
 
             /**
              * @private
+             * @property elCache
              * DOM element cache
              */
             elCache: {},
 
             /**
-             * We cache elements bound by id because when the unload event 
+             * We cache elements bound by id because when the unload event
              * fires, we can no longer use document.getElementById
+             * @method getEl
              * @private
              */
             getEl: function(id) {
@@ -908,27 +1033,21 @@
             clearCache: function() { },
 
             /**
-             * Called by CustomEvent instances to provide a handle to the 
-             * event * that can be removed later on.  Should be package 
-             * protected.
-             * @private
-             */
-            regCE: function(ce) {
-                customEvents.push(ce);
-            },
-
-            /**
-             * @private
              * hook up any deferred listeners
+             * @method _load
+             * @private
              */
             _load: function(e) {
                 loadComplete = true;
+                var EU = YAHOO.util.Event;
+                EU._simpleRemove(window, "load", EU._load);
             },
 
             /**
-             * Polling function that runs before the onload event fires, 
-             * attempting * to attach to DOM Nodes as soon as they are 
+             * Polling function that runs before the onload event fires,
+             * attempting to attach to DOM Nodes as soon as they are
              * available
+             * @method _tryPreloadAttach
              * @private
              */
             _tryPreloadAttach: function() {
@@ -939,10 +1058,9 @@
 
                 this.locked = true;
 
-
-                // keep trying until after the page is loaded.  We need to 
-                // check the page load state prior to trying to bind the 
-                // elements so that we can be certain all elements have been 
+                // keep trying until after the page is loaded.  We need to
+                // check the page load state prior to trying to bind the
+                // elements so that we can be certain all elements have been
                 // tested appropriately
                 var tryAgain = !loadComplete;
                 if (!tryAgain) {
@@ -954,7 +1072,7 @@
 
                 for (var i=0,len=delayedListeners.length; i<len; ++i) {
                     var d = delayedListeners[i];
-                    // There may be a race condition here, so we need to 
+                    // There may be a race condition here, so we need to
                     // verify the array element is usable.
                     if (d) {
 
@@ -963,7 +1081,7 @@
                         var el = this.getEl(d[this.EL]);
 
                         if (el) {
-                            this.on(el, d[this.TYPE], d[this.FN], 
+                            this.on(el, d[this.TYPE], d[this.FN],
                                     d[this.SCOPE], d[this.ADJ_SCOPE]);
                             delete delayedListeners[i];
                         } else {
@@ -975,7 +1093,7 @@
                 delayedListeners = stillDelayed;
 
                 // onAvailable
-                notAvail = [];
+                var notAvail = [];
                 for (i=0,len=onAvailStack.length; i<len ; ++i) {
                     var item = onAvailStack[i];
                     if (item) {
@@ -991,7 +1109,7 @@
                     }
                 }
 
-                retryCount = (stillDelayed.length === 0 && 
+                retryCount = (stillDelayed.length === 0 &&
                                     notAvail.length === 0) ? 0 : retryCount - 1;
 
                 if (tryAgain) {
@@ -1000,37 +1118,111 @@
 
                 this.locked = false;
 
+                return true;
+
+            },
+
+            /**
+             * Removes all listeners attached to the given element via addListener.
+             * Optionally, the node's children can also be purged.
+             * Optionally, you can specify a specific type of event to remove.
+             * @method purgeElement
+             * @param {HTMLElement} el the element to purge
+             * @param {boolean} recurse recursively purge this element's children
+             * as well.  Use with caution.
+             * @param {string} sType optional type of listener to purge. If
+             * left out, all listeners will be removed
+             */
+            purgeElement: function(el, recurse, sType) {
+                var elListeners = this.getListeners(el, sType);
+                if (elListeners) {
+                    for (var i=0,len=elListeners.length; i<len ; ++i) {
+                        var l = elListeners[i];
+                        // can't use the index on the changing collection
+                        //this.removeListener(el, l.type, l.fn, l.index);
+                        this.removeListener(el, l.type, l.fn);
+                    }
+                }
+
+                if (recurse && el && el.childNodes) {
+                    for (i=0,len=el.childNodes.length; i<len ; ++i) {
+                        this.purgeElement(el.childNodes[i], recurse, sType);
+                    }
+                }
+            },
+
+            /**
+             * Returns all listeners attached to the given element via addListener.
+             * Optionally, you can specify a specific type of event to return.
+             * @method getListeners
+             * @param el {HTMLElement} the element to inspect
+             * @param sType {string} optional type of listener to return. If
+             * left out, all listeners will be returned
+             * @return {Object} the listener. Contains the following fields:
+             *    type:   (string)   the type of event
+             *    fn:     (function) the callback supplied to addListener
+             *    obj:    (object)   the custom object supplied to addListener
+             *    adjust: (boolean)  whether or not to adjust the default scope
+             *    index:  (int)      its position in the Event util listener cache
+             */
+            getListeners: function(el, sType) {
+                var elListeners = [];
+                if (listeners && listeners.length > 0) {
+                    for (var i=0,len=listeners.length; i<len ; ++i) {
+                        var l = listeners[i];
+                        if ( l  && l[this.EL] === el &&
+                                (!sType || sType === l[this.TYPE]) ) {
+                            elListeners.push({
+                                type:   l[this.TYPE],
+                                fn:     l[this.FN],
+                                obj:    l[this.SCOPE],
+                                adjust: l[this.ADJ_SCOPE],
+                                index:  i
+                            });
+                        }
+                    }
+                }
+
+                return (elListeners.length) ? elListeners : null;
             },
 
             /**
-             * Removes all listeners registered by pe.event.  Called 
+             * Removes all listeners registered by pe.event.  Called
              * automatically during the unload event.
+             * @method _unload
              * @private
              */
-            _unload: function(e, me) {
+            _unload: function(e) {
+
+                var EU = YAHOO.util.Event;
+
                 for (var i=0,len=unloadListeners.length; i<len; ++i) {
                     var l = unloadListeners[i];
                     if (l) {
-                        var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;
-                        l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );
+                        var scope = (l[EU.ADJ_SCOPE]) ? l[EU.SCOPE]: window;
+                        l[EU.FN].call(scope, EU.getEvent(e), l[EU.SCOPE] );
+                        delete unloadListeners[i];
+                        l=null;
                     }
                 }
 
                 if (listeners && listeners.length > 0) {
-                    for (i=0,len=listeners.length; i<len ; ++i) {
-                        l = listeners[i];
+                    //for (i=0,len=listeners.length; i<len ; ++i) {
+                    var j = listeners.length;
+                    while (j) {
+                        var index = j-1;
+                        l = listeners[index];
                         if (l) {
-                            this.removeListener(l[this.EL], l[this.TYPE], 
-                                    l[this.FN], i);
+                            EU.removeListener(l[EU.EL], l[EU.TYPE],
+                                    l[EU.FN], index);
                         }
-                    }
 
-                    this.clearCache();
-                }
+                        l=null;
+
+                        j = j - 1;
+                    }
 
-                for (i=0,len=customEvents.length; i<len; ++i) {
-                    customEvents[i].unsubscribeAll();
-                    delete customEvents[i];
+                    EU.clearCache();
                 }
 
                 for (i=0,len=legacyEvents.length; i<len; ++i) {
@@ -1039,10 +1231,14 @@
                     // delete the array item
                     delete legacyEvents[i];
                 }
+
+                EU._simpleRemove(window, "unload", EU._unload);
+
             },
 
             /**
              * Returns scrollLeft
+             * @method _getScrollLeft
              * @private
              */
             _getScrollLeft: function() {
@@ -1051,6 +1247,7 @@
 
             /**
              * Returns scrollTop
+             * @method _getScrollTop
              * @private
              */
             _getScrollTop: function() {
@@ -1058,39 +1255,72 @@
             },
 
             /**
-             * Returns the scrollTop and scrollLeft.  Used to calculate the 
+             * Returns the scrollTop and scrollLeft.  Used to calculate the
              * pageX and pageY in Internet Explorer
+             * @method _getScroll
              * @private
              */
             _getScroll: function() {
-                var dd = document.documentElement; db = document.body;
-                if (dd && dd.scrollTop) {
+                var dd = document.documentElement, db = document.body;
+                if (dd && (dd.scrollTop || dd.scrollLeft)) {
                     return [dd.scrollTop, dd.scrollLeft];
                 } else if (db) {
                     return [db.scrollTop, db.scrollLeft];
                 } else {
                     return [0, 0];
                 }
+            },
+
+            /**
+             * Adds a DOM event directly without the caching, cleanup, scope adj, etc
+             *
+             * @param el the elment to bind the handler to
+             * @param {string} sType the type of event handler
+             * @param {function} fn the callback to invoke
+             * @param {boolen} capture or bubble phase
+             * @private
+             */
+            _simpleAdd: function (el, sType, fn, capture) {
+                if (el.addEventListener) {
+                    el.addEventListener(sType, fn, (capture));
+                } else if (el.attachEvent) {
+                    el.attachEvent("on" + sType, fn);
+                }
+            },
+
+            /**
+             * Basic remove listener
+             *
+             * @param el the elment to bind the handler to
+             * @param {string} sType the type of event handler
+             * @param {function} fn the callback to invoke
+             * @param {boolen} capture or bubble phase
+             * @private
+             */
+            _simpleRemove: function (el, sType, fn, capture) {
+                if (el.removeEventListener) {
+                    el.removeEventListener(sType, fn, (capture));
+                } else if (el.detachEvent) {
+                    el.detachEvent("on" + sType, fn);
+                }
             }
         };
+
     } ();
 
     /**
-     * @private
+     * YAHOO.util.Event.on is an alias for addListener
+     * @method on
+     * @see addListener
      */
     YAHOO.util.Event.on = YAHOO.util.Event.addListener;
 
     if (document && document.body) {
         YAHOO.util.Event._load();
     } else {
-        YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load, 
-                YAHOO.util.Event, true);
+        YAHOO.util.Event._simpleAdd(window, "load", YAHOO.util.Event._load);
     }
-
-    YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload, 
-                YAHOO.util.Event, true);
-
+    YAHOO.util.Event._simpleAdd(window, "unload", YAHOO.util.Event._unload);
     YAHOO.util.Event._tryPreloadAttach();
-
 }
 

Modified: trunk/documentation/topic/cms/js/treeview.js
==============================================================================
--- trunk/documentation/topic/cms/js/treeview.js	(original)
+++ trunk/documentation/topic/cms/js/treeview.js	Wed Nov  8 07:00:14 2006
@@ -1,24 +1,21 @@
 /*                                                                                                                                                      
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    
-Code licensed under the BSD License:                                                                                                                    
-http://developer.yahoo.net/yui/license.txt                                                                                                              
-version: 0.10.0                                                                                                                                         
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 0.11.3
 */ 
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
-
 /**
  * Contains the tree view state data and the root node.  This is an
  * ordered tree; child nodes will be displayed in the order created, and
  * there currently is no way to change this.
  *
  * @constructor
- * @todo graft (appendBefore, appendAfter)
- * @param {string} id The id of the element that the tree will be inserted
- * into.
+ * @param {string|HTMLElement} id The id of the element, or the element
+ * itself that the tree will be inserted into.
  */
 YAHOO.widget.TreeView = function(id) {
-	if (id) { this.init(id); }
+    if (id) { this.init(id); }
 };
 
 /**
@@ -36,6 +33,12 @@
      */
     id: null,
 
+    /**
+     * The host element for this tree
+     * @private
+     */
+    _el: null,
+
      /**
      * Flat collection of all nodes in this tree
      *
@@ -85,7 +88,8 @@
     /**
      * Sets up the animation for expanding children
      *
-     * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
+     * @param {string} the type of animation (acceptable values defined in 
+     * YAHOO.widget.TVAnim)
      */
     setExpandAnim: function(type) {
         if (YAHOO.widget.TVAnim.isValid(type)) {
@@ -96,7 +100,8 @@
     /**
      * Sets up the animation for collapsing children
      *
-     * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
+     * @param {string} the type of animation (acceptable values defined in 
+     * YAHOO.widget.TVAnim)
      */
     setCollapseAnim: function(type) {
         if (YAHOO.widget.TVAnim.isValid(type)) {
@@ -173,16 +178,22 @@
     /**
      * Initializes the tree
      *
-     * @parm {string} id the id of the element that will hold the tree
+     * @parm {string|HTMLElement} id the id of the element that will hold the tree
      * @private
      */
     init: function(id) {
 
         this.id = id;
+
+        if ("string" !== typeof id) {
+            this._el = id;
+            this.id = this.generateId(id);
+        }
+
         this._nodes = [];
 
         // store a global reference
-        YAHOO.widget.TreeView.trees[id] = this;
+        YAHOO.widget.TreeView.trees[this.id] = this;
 
         // Set up the root node
         this.root = new YAHOO.widget.RootNode(this);
@@ -195,11 +206,22 @@
      */
     draw: function() {
         var html = this.root.getHtml();
-        document.getElementById(this.id).innerHTML = html;
+        this.getEl().innerHTML = html;
         this.firstDraw = false;
     },
 
     /**
+     * Returns the tree's host element
+     * @return {HTMLElement} the host element
+     */
+    getEl: function() {
+        if (! this._el) {
+            this._el = document.getElementById(this.id);
+        }
+        return this._el;
+    },
+
+    /**
      * Nodes register themselves with the tree instance when they are created.
      *
      * @param node {Node} the node to register
@@ -267,8 +289,7 @@
 
     /**
      * Returns a node that has a matching property and value in the data
-     * object that was passed into its constructor.  Provides a flexible
-     * way for the implementer to get a particular node.
+     * object that was passed into its constructor.
      *
      * @param {object} property the property to search (usually a string)
      * @param {object} value the value we want to find (usuall an int or string)
@@ -286,8 +307,28 @@
     },
 
     /**
-     * Removes the node and its children, and optionally refreshes the branch 
-     * of the tree that was affected.
+     * Returns a collection of nodes that have a matching property 
+     * and value in the data object that was passed into its constructor.  
+     *
+     * @param {object} property the property to search (usually a string)
+     * @param {object} value the value we want to find (usuall an int or string)
+     * @return {Array} the matching collection of nodes, null if no match
+     */
+    getNodesByProperty: function(property, value) {
+        var values = [];
+        for (var i in this._nodes) {
+            var n = this._nodes[i];
+            if (n.data && value == n.data[property]) {
+                values.push(n);
+            }
+        }
+
+        return (values.length) ? values : null;
+    },
+
+    /**
+     * Removes the node and its children, and optionally refreshes the 
+     * branch of the tree that was affected.
      * @param {Node} The node to remove
      * @param {boolean} autoRefresh automatically refreshes branch if true
      * @return {boolean} False is there was a problem, true otherwise.
@@ -324,12 +365,14 @@
      * @param {Node} node the node to purge
      */
     removeChildren: function(node) { 
-        for (var i=0, len=node.children.length;i<len;++i) {
-            this._deleteNode(node.children[i]);
+        while (node.children.length) {
+             this._deleteNode(node.children[0]);
         }
 
         node.childrenRendered = false;
         node.dynamicLoadComplete = false;
+        // node.collapse();
+        node.expand();
         node.collapse();
     },
 
@@ -338,15 +381,26 @@
      * @private
      */
     _deleteNode: function(node) { 
-        var p = node.parent;
-
         // Remove all the child nodes first
         this.removeChildren(node);
 
+        // Remove the node from the tree
+        this.popNode(node);
+    },
+
+    /**
+     * Removes the node from the tree, preserving the child collection 
+     * to make it possible to insert the branch into another part of the 
+     * tree, or another tree.
+     * @param {Node} the node to remove
+     */
+    popNode: function(node) { 
+        var p = node.parent;
+
         // Update the parent's collection of children
         var a = [];
 
-        for (i=0, len=p.children.length;i<len;++i) {
+        for (var i=0, len=p.children.length;i<len;++i) {
             if (p.children[i] != node) {
                 a[a.length] = p.children[i];
             }
@@ -357,29 +411,54 @@
         // reset the childrenRendered flag for the parent
         p.childrenRendered = false;
 
-         // Update the sibling relationship                                                                                                                       
-        if (node.previousSibling) {                                                                                                                              
-            node.previousSibling.nextSibling = node.nextSibling;                                                                                                   
-        }                                                                                                                                                        
+         // Update the sibling relationship
+        if (node.previousSibling) {
+            node.previousSibling.nextSibling = node.nextSibling;
+        }
 
-        if (node.nextSibling) {                                                                                                                                  
-            node.nextSibling.previousSibling = node.previousSibling;                                                                                               
+        if (node.nextSibling) {
+            node.nextSibling.previousSibling = node.previousSibling;
         }
 
+        node.parent = null;
+        node.previousSibling = null;
+        node.nextSibling = null;
+        node.tree = null;
+
         // Update the tree's node collection 
         delete this._nodes[node.index];
     },
 
     /**
+     * toString
+     * @return {string} string representation of the tree
+     */
+    toString: function() {
+        return "TreeView " + this.id;
+    },
+
+    /**
+     * private
+     */
+    generateId: function(el) {
+        var id = el.id;
+
+        if (!id) {
+            id = "yui-tv-auto-id-" + YAHOO.widget.TreeView.counter;
+            YAHOO.widget.TreeView.counter++;
+        }
+
+        return id;
+    },
+
+    /**
      * Abstract method that is executed when a node is expanded
-     *
      * @param node {Node} the node that was expanded
      */
     onExpand: function(node) { },
 
     /**
      * Abstract method that is executed when a node is collapsed
-     *
      * @param node {Node} the node that was collapsed.
      */
     onCollapse: function(node) { }
@@ -395,6 +474,11 @@
 YAHOO.widget.TreeView.trees = [];
 
 /**
+ * @private
+ */
+YAHOO.widget.TreeView.counter = 0;
+
+/**
  * Global method for getting a tree by its id.  Used in the generated
  * tree html.
  *
@@ -402,8 +486,8 @@
  * @return {TreeView} the tree instance requested, null if not found.
  */
 YAHOO.widget.TreeView.getTree = function(treeId) {
-	var t = YAHOO.widget.TreeView.trees[treeId];
-	return (t) ? t : null;
+    var t = YAHOO.widget.TreeView.trees[treeId];
+    return (t) ? t : null;
 };
 
 /**
@@ -415,8 +499,8 @@
  * @return {Node} the node instance requested, null if not found
  */
 YAHOO.widget.TreeView.getNode = function(treeId, nodeIndex) {
-	var t = YAHOO.widget.TreeView.getTree(treeId);
-	return (t) ? t.getNodeByIndex(nodeIndex) : null;
+    var t = YAHOO.widget.TreeView.getTree(treeId);
+    return (t) ? t.getNodeByIndex(nodeIndex) : null;
 };
 
 /**
@@ -428,57 +512,43 @@
  * @param {boolean} capture if true event is capture phase, bubble otherwise
  */
 YAHOO.widget.TreeView.addHandler = function (el, sType, fn, capture) {
-	capture = (capture) ? true : false;
-	if (el.addEventListener) {
-		el.addEventListener(sType, fn, capture);
-	} else if (el.attachEvent) {
-		el.attachEvent("on" + sType, fn);
-	} else {
-		el["on" + sType] = fn;
-	}
+    capture = (capture) ? true : false;
+    if (el.addEventListener) {
+        el.addEventListener(sType, fn, capture);
+    } else if (el.attachEvent) {
+        el.attachEvent("on" + sType, fn);
+    } else {
+        el["on" + sType] = fn;
+    }
 };
 
 /**
  * Attempts to preload the images defined in the styles used to draw the tree by
  * rendering off-screen elements that use the styles.
  */
-YAHOO.widget.TreeView.preload = function() {
+YAHOO.widget.TreeView.preload = function(prefix) {
+    prefix = prefix || "ygtv";
+    var styles = ["tn","tm","tmh","tp","tph","ln","lm","lmh","lp","lph","loading"];
 
-	var styles = [
-		"ygtvtn",	
-		"ygtvtm",	
-		"ygtvtmh",	
-		"ygtvtp",	
-		"ygtvtph",	
-		"ygtvln",	
-		"ygtvlm",	
-		"ygtvlmh",	
-		"ygtvlp",	
-		"ygtvlph",	
-		"ygtvloading"
-		];
-
-	var sb = [];
-	
-	for (var i = 0; i < styles.length; ++i) { 
-		sb[sb.length] = '<span class="' + styles[i] + '">&nbsp;</span>';
-	}
+    var sb = [];
+    
+    for (var i = 0; i < styles.length; ++i) { 
+        sb[sb.length] = '<span class="' + prefix + styles[i] + '">&#160;</span>';
+    }
 
-	var f = document.createElement("div");
-	var s = f.style;
-	s.position = "absolute";
-	s.top = "-1000px";
-	s.left = "-1000px";
-	f.innerHTML = sb.join("");
+    var f = document.createElement("DIV");
+    var s = f.style;
+    s.position = "absolute";
+    s.top = "-1000px";
+    s.left = "-1000px";
+    f.innerHTML = sb.join("");
 
-	document.body.appendChild(f);
+    document.body.appendChild(f);
 };
 
 YAHOO.widget.TreeView.addHandler(window, 
                 "load", YAHOO.widget.TreeView.preload);
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
-
 /**
  * The base class for all tree nodes.  The node's presentation and behavior in
  * response to mouse events is handled in Node subclasses.
@@ -490,7 +560,7 @@
  * @constructor
  */
 YAHOO.widget.Node = function(oData, oParent, expanded) {
-	if (oParent) { this.init(oData, oParent, expanded); }
+    if (oData) { this.init(oData, oParent, expanded); }
 };
 
 YAHOO.widget.Node.prototype = {
@@ -668,44 +738,162 @@
      * @param expanded {boolean} the initial expanded/collapsed state
      */
     init: function(oData, oParent, expanded) {
-        this.data		= oData;
-        this.children	= [];
-        this.index		= YAHOO.widget.TreeView.nodeCount;
+        this.data       = oData;
+        this.children   = [];
+        this.index      = YAHOO.widget.TreeView.nodeCount;
         ++YAHOO.widget.TreeView.nodeCount;
-        this.expanded	= expanded;
+        this.expanded   = expanded;
 
         // oParent should never be null except when we create the root node.
         if (oParent) {
-            this.tree			= oParent.tree;
-            this.parent			= oParent;
-            this.href			= "javascript:" + this.getToggleLink();
-            this.depth			= oParent.depth + 1;
-            this.multiExpand	= oParent.multiExpand;
-
             oParent.appendChild(this);
         }
     },
 
     /**
+     * Certain properties for the node cannot be set until the parent
+     * is known. This is called after the node is inserted into a tree.
+     * the parent is also applied to this node's children in order to
+     * make it possible to move a branch from one tree to another.
+     * @param {Node} parentNode this node's parent node
+     * @return {boolean} true if the application was successful
+     */
+    applyParent: function(parentNode) {
+        if (!parentNode) {
+            return false;
+        }
+
+        this.tree   = parentNode.tree;
+        this.parent = parentNode;
+        this.depth  = parentNode.depth + 1;
+
+        if (! this.href) {
+            this.href = "javascript:" + this.getToggleLink();
+        }
+
+        if (! this.multiExpand) {
+            this.multiExpand = parentNode.multiExpand;
+        }
+
+        this.tree.regNode(this);
+        parentNode.childrenRendered = false;
+
+        // cascade update existing children
+        for (var i=0, len=this.children.length;i<len;++i) {
+            this.children[i].applyParent(this);
+        }
+
+        return true;
+    },
+
+    /**
      * Appends a node to the child collection.
      *
-     * @param node {Node} the new node
+     * @param childNode {Node} the new node
      * @return {Node} the child node
      * @private
-     * @TODO insertBefore, insertAfter
      */
-    appendChild: function(node) {
+    appendChild: function(childNode) {
         if (this.hasChildren()) {
             var sib = this.children[this.children.length - 1];
-            sib.nextSibling = node;
-            node.previousSibling = sib;
+            sib.nextSibling = childNode;
+            childNode.previousSibling = sib;
         }
+        this.children[this.children.length] = childNode;
+        childNode.applyParent(this);
 
-        this.tree.regNode(node);
-        this.children[this.children.length] = node;
-        this.childrenRendered = false;
-        return node;
+        return childNode;
+    },
 
+    /**
+     * Appends this node to the supplied node's child collection
+     * @param parentNode {Node} the node to append to.
+     * @return {Node} The appended node
+     */
+    appendTo: function(parentNode) {
+        return parentNode.appendChild(this);
+    },
+
+    /**
+    * Inserts this node before this supplied node
+    *
+    * @param node {Node} the node to insert this node before
+    * @return {Node} the inserted node
+    */
+    insertBefore: function(node) {
+        var p = node.parent;
+        if (p) {
+
+            if (this.tree) {
+                this.tree.popNode(this);
+            }
+
+            var refIndex = node.isChildOf(p);
+            p.children.splice(refIndex, 0, this);
+            if (node.previousSibling) {
+                node.previousSibling.nextSibling = this;
+            }
+            this.previousSibling = node.previousSibling;
+            this.nextSibling = node;
+            node.previousSibling = this;
+
+            this.applyParent(p);
+        }
+
+        return this;
+    },
+ 
+    /**
+    * Inserts this node after the supplied node
+    *
+    * @param node {Node} the node to insert after
+    * @return {Node} the inserted node
+    */
+    insertAfter: function(node) {
+        var p = node.parent;
+        if (p) {
+
+            if (this.tree) {
+                this.tree.popNode(this);
+            }
+
+            var refIndex = node.isChildOf(p);
+
+            if (!node.nextSibling) {
+                return this.appendTo(p);
+            }
+
+            p.children.splice(refIndex + 1, 0, this);
+
+            node.nextSibling.previousSibling = this;
+            this.previousSibling = node;
+            this.nextSibling = node.nextSibling;
+            node.nextSibling = this;
+
+            this.applyParent(p);
+        }
+
+        return this;
+    },
+
+    /**
+    * Returns true if the Node is a child of supplied Node
+    *
+    * @param parentNode {Node} the Node to check
+    * @return {boolean} The node index if this Node is a child of 
+    *                   supplied Node, else -1.
+    * @private
+    */
+    isChildOf: function(parentNode) {
+        if (parentNode && parentNode.children) {
+            for (var i=0, len=parentNode.children.length; i<len ; ++i) {
+                if (parentNode.children[i] === this) {
+                    return i;
+                }
+            }
+        }
+
+        return -1;
     },
 
     /**
@@ -1238,12 +1426,18 @@
                 el.className = this.getStyle();
             }
         }
+    },
+
+    /**
+     * toString
+     * @return {string} string representation of the node
+     */
+    toString: function() {
+        return "Node (" + this.index + ")";
     }
 
 };
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
-
 /**
  * A custom YAHOO.widget.Node that handles the unique nature of 
  * the virtual, presentationless root node.
@@ -1265,6 +1459,7 @@
 	 */
 	this.tree = oTree;
 };
+
 YAHOO.widget.RootNode.prototype = new YAHOO.widget.Node();
 
 // overrides YAHOO.widget.Node
@@ -1272,8 +1467,13 @@
 	return ""; 
 };
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+YAHOO.widget.RootNode.prototype.toString = function() { 
+    return "RootNode";
+};
 
+YAHOO.widget.RootNode.prototype.loadComplete = function() { 
+    this.tree.draw();
+};
 /**
  * The default node presentation.  The first parameter should be
  * either a string that will be used as the node's label, or an object
@@ -1290,12 +1490,16 @@
  * @param expanded {boolean} the initial expanded/collapsed state
  */
 YAHOO.widget.TextNode = function(oData, oParent, expanded) {
-    this.type = "TextNode";
+    // this.type = "TextNode";
 
-	if (oParent) { 
-		this.init(oData, oParent, expanded);
-		this.setUpLabel(oData);
-	}
+    if (oData) { 
+        this.init(oData, oParent, expanded);
+        this.setUpLabel(oData);
+    }
+
+    /**
+     * @private
+     */
 };
 
 YAHOO.widget.TextNode.prototype = new YAHOO.widget.Node();
@@ -1330,26 +1534,26 @@
  * @param oData string containing the label, or an object with a label property
  */
 YAHOO.widget.TextNode.prototype.setUpLabel = function(oData) { 
-	if (typeof oData == "string") {
-		oData = { label: oData };
-	}
-	this.label = oData.label;
-	
-	// update the link
-	if (oData.href) {
-		this.href = oData.href;
-	}
+    if (typeof oData == "string") {
+        oData = { label: oData };
+    }
+    this.label = oData.label;
+    
+    // update the link
+    if (oData.href) {
+        this.href = oData.href;
+    }
 
-	// set the target
-	if (oData.target) {
-		this.target = oData.target;
-	}
+    // set the target
+    if (oData.target) {
+        this.target = oData.target;
+    }
 
     if (oData.style) {
         this.labelStyle = oData.style;
     }
 
-	this.labelElId = "ygtvlabelel" + this.index;
+    this.labelElId = "ygtvlabelel" + this.index;
 };
 
 /**
@@ -1358,38 +1562,38 @@
  * @return {object} the element
  */
 YAHOO.widget.TextNode.prototype.getLabelEl = function() { 
-	return document.getElementById(this.labelElId);
+    return document.getElementById(this.labelElId);
 };
 
 // overrides YAHOO.widget.Node
 YAHOO.widget.TextNode.prototype.getNodeHtml = function() { 
-	var sb = [];
+    var sb = [];
 
-	sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
-	sb[sb.length] = '<tr>';
-	
-	for (i=0;i<this.depth;++i) {
-		// sb[sb.length] = '<td class="ygtvdepthcell">&nbsp;</td>';
-		sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
-	}
+    sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
+    sb[sb.length] = '<tr>';
+    
+    for (i=0;i<this.depth;++i) {
+        // sb[sb.length] = '<td class="ygtvdepthcell">&#160;</td>';
+        sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&#160;</td>';
+    }
 
-	var getNode = 'YAHOO.widget.TreeView.getNode(\'' +
-					this.tree.id + '\',' + this.index + ')';
+    var getNode = 'YAHOO.widget.TreeView.getNode(\'' +
+                    this.tree.id + '\',' + this.index + ')';
 
-	sb[sb.length] = '<td';
-	// sb[sb.length] = ' onselectstart="return false"';
-	sb[sb.length] = ' id="' + this.getToggleElId() + '"';
-	sb[sb.length] = ' class="' + this.getStyle() + '"';
-	if (this.hasChildren(true)) {
-		sb[sb.length] = ' onmouseover="this.className=';
-		sb[sb.length] = getNode + '.getHoverStyle()"';
-		sb[sb.length] = ' onmouseout="this.className=';
-		sb[sb.length] = getNode + '.getStyle()"';
-	}
-	sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">';
+    sb[sb.length] = '<td';
+    // sb[sb.length] = ' onselectstart="return false"';
+    sb[sb.length] = ' id="' + this.getToggleElId() + '"';
+    sb[sb.length] = ' class="' + this.getStyle() + '"';
+    if (this.hasChildren(true)) {
+        sb[sb.length] = ' onmouseover="this.className=';
+        sb[sb.length] = getNode + '.getHoverStyle()"';
+        sb[sb.length] = ' onmouseout="this.className=';
+        sb[sb.length] = getNode + '.getStyle()"';
+    }
+    sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">';
 
     /*
-	sb[sb.length] = '<img id="' + this.getSpacerId() + '"';
+    sb[sb.length] = '<img id="' + this.getSpacerId() + '"';
     sb[sb.length] = ' alt=""';
     sb[sb.length] = ' tabindex=0';
     sb[sb.length] = ' src="' + this.spacerPath + '"';
@@ -1399,32 +1603,32 @@
     sb[sb.length] = ' />';
     */
 
-	sb[sb.length] = '&nbsp;';
+    sb[sb.length] = '&#160;';
 
-	sb[sb.length] = '</td>';
-	sb[sb.length] = '<td>';
-	sb[sb.length] = '<a';
-	sb[sb.length] = ' id="' + this.labelElId + '"';
-	sb[sb.length] = ' class="' + this.labelStyle + '"';
-	sb[sb.length] = ' href="' + this.href + '"';
-	sb[sb.length] = ' target="' + this.target + '"';
-	sb[sb.length] = ' onclick="return ' + getNode + '.onLabelClick(' + getNode +')"';
-	if (this.hasChildren(true)) {
-		sb[sb.length] = ' onmouseover="document.getElementById(\'';
-		sb[sb.length] = this.getToggleElId() + '\').className=';
-		sb[sb.length] = getNode + '.getHoverStyle()"';
-		sb[sb.length] = ' onmouseout="document.getElementById(\'';
-		sb[sb.length] = this.getToggleElId() + '\').className=';
-		sb[sb.length] = getNode + '.getStyle()"';
-	}
-	sb[sb.length] = ' >';
-	sb[sb.length] = this.label;
-	sb[sb.length] = '</a>';
-	sb[sb.length] = '</td>';
-	sb[sb.length] = '</tr>';
-	sb[sb.length] = '</table>';
+    sb[sb.length] = '</td>';
+    sb[sb.length] = '<td>';
+    sb[sb.length] = '<a';
+    sb[sb.length] = ' id="' + this.labelElId + '"';
+    sb[sb.length] = ' class="' + this.labelStyle + '"';
+    sb[sb.length] = ' href="' + this.href + '"';
+    sb[sb.length] = ' target="' + this.target + '"';
+    sb[sb.length] = ' onclick="return ' + getNode + '.onLabelClick(' + getNode +')"';
+    if (this.hasChildren(true)) {
+        sb[sb.length] = ' onmouseover="document.getElementById(\'';
+        sb[sb.length] = this.getToggleElId() + '\').className=';
+        sb[sb.length] = getNode + '.getHoverStyle()"';
+        sb[sb.length] = ' onmouseout="document.getElementById(\'';
+        sb[sb.length] = this.getToggleElId() + '\').className=';
+        sb[sb.length] = getNode + '.getStyle()"';
+    }
+    sb[sb.length] = ' >';
+    sb[sb.length] = this.label;
+    sb[sb.length] = '</a>';
+    sb[sb.length] = '</td>';
+    sb[sb.length] = '</tr>';
+    sb[sb.length] = '</table>';
 
-	return sb.join("");
+    return sb.join("");
 };
 
 /**
@@ -1436,7 +1640,10 @@
 YAHOO.widget.TextNode.prototype.onLabelClick = function(me) { 
     //return true;
 };
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+YAHOO.widget.TextNode.prototype.toString = function() { 
+    return "TextNode (" + this.index + ") " + this.label;
+};
 
 /**
  * A menu-specific implementation that differs from TextNode in that only 
@@ -1445,7 +1652,7 @@
  * @constructor
  */
 YAHOO.widget.MenuNode = function(oData, oParent, expanded) {
-	if (oParent) { 
+	if (oData) { 
 		this.init(oData, oParent, expanded);
 		this.setUpLabel(oData);
 	}
@@ -1456,11 +1663,17 @@
      */
 	this.multiExpand = false;
 
+    /**
+     * @private
+     */
+
 };
 
 YAHOO.widget.MenuNode.prototype = new YAHOO.widget.TextNode();
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+YAHOO.widget.MenuNode.prototype.toString = function() { 
+    return "MenuNode (" + this.index + ") " + this.label;
+};
 
 /**
  * This implementation takes either a string or object for the
@@ -1479,7 +1692,7 @@
  * have an icon
  */
 YAHOO.widget.HTMLNode = function(oData, oParent, expanded, hasIcon) {
-    if (oParent) { 
+    if (oData) { 
         this.init(oData, oParent, expanded);
         this.initContent(oData, hasIcon);
     }
@@ -1488,8 +1701,8 @@
 YAHOO.widget.HTMLNode.prototype = new YAHOO.widget.Node();
 
 /**
- * The CSS class for the label href.  Defaults to ygtvlabel, but can be
- * overridden to provide a custom presentation for a specific node.
+ * The CSS class for the html content container.  Defaults to ygtvhtml, but 
+ * can be overridden to provide a custom presentation for a specific node.
  *
  * @type string
  */
@@ -1524,6 +1737,10 @@
     this.html = oData.html;
     this.contentElId = "ygtvcontentel" + this.index;
     this.hasIcon = hasIcon;
+
+    /**
+     * @private
+     */
 };
 
 /**
@@ -1543,7 +1760,7 @@
     sb[sb.length] = '<tr>';
     
     for (i=0;i<this.depth;++i) {
-        sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
+        sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&#160;</td>';
     }
 
     if (this.hasIcon) {
@@ -1559,7 +1776,7 @@
             sb[sb.length] = 'YAHOO.widget.TreeView.getNode(\'';
             sb[sb.length] = this.tree.id + '\',' + this.index +  ').getStyle()"';
         }
-        sb[sb.length] = '>&nbsp;</td>';
+        sb[sb.length] = '>&#160;</td>';
     }
 
     sb[sb.length] = '<td';
@@ -1574,7 +1791,9 @@
     return sb.join("");
 };
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+YAHOO.widget.HTMLNode.prototype.toString = function() { 
+    return "HTMLNode (" + this.index + ")";
+};
 
 /**
  * A static factory class for tree view expand/collapse animations
@@ -1625,8 +1844,6 @@
     };
 } ();
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
-
 /**
  * A 1/2 second fade-in animation.
  *
@@ -1635,22 +1852,22 @@
  * @param callback {function} function to invoke when the animation is finished
  */
 YAHOO.widget.TVFadeIn = function(el, callback) {
-	/**
-	 * The element to animate
+    /**
+     * The element to animate
      * @type HTMLElement
-	 */
-	this.el = el;
+     */
+    this.el = el;
 
-	/**
-	 * the callback to invoke when the animation is complete
-	 *
-	 * @type function
-	 */
-	this.callback = callback;
+    /**
+     * the callback to invoke when the animation is complete
+     *
+     * @type function
+     */
+    this.callback = callback;
 
-	/**
-	 * @private
-	 */
+    /**
+     * @private
+     */
 };
 
 /**
@@ -1682,11 +1899,13 @@
      */
     onComplete: function() {
         this.callback();
+    },
+
+    toString: function() {
+        return "TVFadeIn";
     }
 };
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
-
 /**
  * A 1/2 second fade out animation.
  *
@@ -1695,22 +1914,22 @@
  * @param callback {Function} function to invoke when the animation is finished
  */
 YAHOO.widget.TVFadeOut = function(el, callback) {
-	/**
-	 * The element to animate
+    /**
+     * The element to animate
      * @type HTMLElement
-	 */
-	this.el = el;
+     */
+    this.el = el;
 
-	/**
-	 * the callback to invoke when the animation is complete
-	 *
-	 * @type function
-	 */
-	this.callback = callback;
+    /**
+     * the callback to invoke when the animation is complete
+     *
+     * @type function
+     */
+    this.callback = callback;
 
-	/**
-	 * @private
-	 */
+    /**
+     * @private
+     */
 };
 
 /**
@@ -1739,6 +1958,10 @@
         // s.opacity = 1;
         s.filter = "alpha(opacity=100)";
         this.callback();
+    },
+
+    toString: function() {
+        return "TVFadeOut";
     }
 };
 

Modified: trunk/documentation/topic/cms/js/yahoo.js
==============================================================================
--- trunk/documentation/topic/cms/js/yahoo.js	(original)
+++ trunk/documentation/topic/cms/js/yahoo.js	Wed Nov  8 07:00:14 2006
@@ -1,17 +1,26 @@
-/*                                                                                                                                                      
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    
-Code licensed under the BSD License:                                                                                                                    
-http://developer.yahoo.net/yui/license.txt                                                                                                              
-version: 0.10.0                                                                                                                                         
-*/ 
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+Version: 0.11.4
+*/
 
-/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+/**
+ * The YAHOO object is the single global object used by YUI Library.  It
+ * contains utility function for setting up namespaces, inheritance, and
+ * logging.  YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces
+ * created automatically for and used by the library.
+ * @module YAHOO
+ */
 
 /**
- * The Yahoo global namespace
- * @constructor
+ * The YAHOO global namespace object
+ * @class YAHOO
+ * @static
  */
-var YAHOO = window.YAHOO || {};
+if (typeof YAHOO == "undefined") {
+    YAHOO = {};
+}
 
 /**
  * Returns the namespace specified and creates it if it doesn't exist
@@ -22,40 +31,77 @@
  * Either of the above would create YAHOO.property, then
  * YAHOO.property.package
  *
- * @param  {String} sNameSpace String representation of the desired 
- *                             namespace
- * @return {Object}            A reference to the namespace object
+ * Be careful when naming packages. Reserved words may work in some browsers
+ * and not others. For instance, the following will fail in Safari:
+ *
+ * YAHOO.namespace("really.long.nested.namespace");
+ *
+ * This fails because "long" is a future reserved word in ECMAScript
+ * @method namespace
+ * @static
+ * @param  {String} ns The name of the namespace
+ * @return {Object}    A reference to the namespace object
  */
-YAHOO.namespace = function( sNameSpace ) {
+YAHOO.namespace = function(ns) {
 
-    if (!sNameSpace || !sNameSpace.length) {
+    if (!ns || !ns.length) {
         return null;
     }
 
-    var levels = sNameSpace.split(".");
-
-    var currentNS = YAHOO;
+    var levels = ns.split(".");
+    var nsobj = YAHOO;
 
     // YAHOO is implied, so it is ignored if it is included
     for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {
-        currentNS[levels[i]] = currentNS[levels[i]] || {};
-        currentNS = currentNS[levels[i]];
+        nsobj[levels[i]] = nsobj[levels[i]] || {};
+        nsobj = nsobj[levels[i]];
     }
 
-    return currentNS;
+    return nsobj;
 };
 
 /**
- * Global log method.
+ * Uses YAHOO.widget.Logger to output a log message, if the widget is available.
+ *
+ * @method log
+ * @static
+ * @param  {string}  sMsg       The message to log.
+ * @param  {string}  sCategory  The log category for the message.  Default
+ *                              categories are "info", "warn", "error", time".
+ *                              Custom categories can be used as well. (opt)
+ * @param  {string}  sSource    The source of the the message (opt)
+ * @return {boolean}            True if the log operation was successful.
  */
-YAHOO.log = function(sMsg,sCategory) {
-    if(YAHOO.widget.Logger) {
-        YAHOO.widget.Logger.log(null, sMsg, sCategory);
+YAHOO.log = function(sMsg, sCategory, sSource) {
+    var l = YAHOO.widget.Logger;
+    if(l && l.log) {
+        return l.log(sMsg, sCategory, sSource);
     } else {
         return false;
     }
 };
 
+/**
+ * Utility to set up the prototype, constructor and superclass properties to
+ * support an inheritance strategy that can chain constructors and methods.
+ *
+ * @method extend
+ * @static
+ * @param {function} subclass   the object to modify
+ * @param {function} superclass the object to inherit
+ */
+YAHOO.extend = function(subclass, superclass) {
+    var f = function() {};
+    f.prototype = superclass.prototype;
+    subclass.prototype = new f();
+    subclass.prototype.constructor = subclass;
+    subclass.superclass = superclass.prototype;
+    if (superclass.prototype.constructor == Object.prototype.constructor) {
+        superclass.prototype.constructor = superclass;
+    }
+};
+
 YAHOO.namespace("util");
 YAHOO.namespace("widget");
 YAHOO.namespace("example");
+



More information about the chatter mailing list