PageRenderTime 71ms CodeModel.GetById 26ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-war/src/main/webapp/scripts/yui/yahoo/yahoo-debug.js

http://github.com/hudson/hudson
JavaScript | 974 lines | 366 code | 85 blank | 523 comment | 108 complexity | 69831ed4b6c0b1dd3985bc3cb4a9ac14 MD5 | raw file
  1/*
  2Copyright (c) 2008, Yahoo! Inc. All rights reserved.
  3Code licensed under the BSD License:
  4http://developer.yahoo.net/yui/license.txt
  5version: 2.5.1
  6*/
  7/**
  8 * The YAHOO object is the single global object used by YUI Library.  It
  9 * contains utility function for setting up namespaces, inheritance, and
 10 * logging.  YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces
 11 * created automatically for and used by the library.
 12 * @module yahoo
 13 * @title  YAHOO Global
 14 */
 15
 16/**
 17 * YAHOO_config is not included as part of the library.  Instead it is an 
 18 * object that can be defined by the implementer immediately before 
 19 * including the YUI library.  The properties included in this object
 20 * will be used to configure global properties needed as soon as the 
 21 * library begins to load.
 22 * @class YAHOO_config
 23 * @static
 24 */
 25
 26/**
 27 * A reference to a function that will be executed every time a YAHOO module
 28 * is loaded.  As parameter, this function will receive the version
 29 * information for the module. See <a href="YAHOO.env.html#getVersion">
 30 * YAHOO.env.getVersion</a> for the description of the version data structure.
 31 * @property listener
 32 * @type Function
 33 * @static
 34 * @default undefined
 35 */
 36
 37/**
 38 * Set to true if the library will be dynamically loaded after window.onload.
 39 * Defaults to false 
 40 * @property injecting
 41 * @type boolean
 42 * @static
 43 * @default undefined
 44 */
 45
 46/**
 47 * Instructs the yuiloader component to dynamically load yui components and
 48 * their dependencies.  See the yuiloader documentation for more information
 49 * about dynamic loading
 50 * @property load
 51 * @static
 52 * @default undefined
 53 * @see yuiloader
 54 */
 55
 56/**
 57 * Forces the use of the supplied locale where applicable in the library
 58 * @property locale
 59 * @type string
 60 * @static
 61 * @default undefined
 62 */
 63
 64if (typeof YAHOO == "undefined" || !YAHOO) {
 65    /**
 66     * The YAHOO global namespace object.  If YAHOO is already defined, the
 67     * existing YAHOO object will not be overwritten so that defined
 68     * namespaces are preserved.
 69     * @class YAHOO
 70     * @static
 71     */
 72    var YAHOO = {};
 73}
 74
 75/**
 76 * Returns the namespace specified and creates it if it doesn't exist
 77 * <pre>
 78 * YAHOO.namespace("property.package");
 79 * YAHOO.namespace("YAHOO.property.package");
 80 * </pre>
 81 * Either of the above would create YAHOO.property, then
 82 * YAHOO.property.package
 83 *
 84 * Be careful when naming packages. Reserved words may work in some browsers
 85 * and not others. For instance, the following will fail in Safari:
 86 * <pre>
 87 * YAHOO.namespace("really.long.nested.namespace");
 88 * </pre>
 89 * This fails because "long" is a future reserved word in ECMAScript
 90 *
 91 * @method namespace
 92 * @static
 93 * @param  {String*} arguments 1-n namespaces to create 
 94 * @return {Object}  A reference to the last namespace object created
 95 */
 96YAHOO.namespace = function() {
 97    var a=arguments, o=null, i, j, d;
 98    for (i=0; i<a.length; i=i+1) {
 99        d=a[i].split(".");
100        o=YAHOO;
101
102        // YAHOO is implied, so it is ignored if it is included
103        for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
104            o[d[j]]=o[d[j]] || {};
105            o=o[d[j]];
106        }
107    }
108
109    return o;
110};
111
112/**
113 * Uses YAHOO.widget.Logger to output a log message, if the widget is
114 * available.
115 *
116 * @method log
117 * @static
118 * @param  {String}  msg  The message to log.
119 * @param  {String}  cat  The log category for the message.  Default
120 *                        categories are "info", "warn", "error", time".
121 *                        Custom categories can be used as well. (opt)
122 * @param  {String}  src  The source of the the message (opt)
123 * @return {Boolean}      True if the log operation was successful.
124 */
125YAHOO.log = function(msg, cat, src) {
126    var l=YAHOO.widget.Logger;
127    if(l && l.log) {
128        return l.log(msg, cat, src);
129    } else {
130        return false;
131    }
132};
133
134/**
135 * Registers a module with the YAHOO object
136 * @method register
137 * @static
138 * @param {String}   name    the name of the module (event, slider, etc)
139 * @param {Function} mainClass a reference to class in the module.  This
140 *                             class will be tagged with the version info
141 *                             so that it will be possible to identify the
142 *                             version that is in use when multiple versions
143 *                             have loaded
144 * @param {Object}   data      metadata object for the module.  Currently it
145 *                             is expected to contain a "version" property
146 *                             and a "build" property at minimum.
147 */
148YAHOO.register = function(name, mainClass, data) {
149    var mods = YAHOO.env.modules;
150    if (!mods[name]) {
151        mods[name] = { versions:[], builds:[] };
152    }
153    var m=mods[name],v=data.version,b=data.build,ls=YAHOO.env.listeners;
154    m.name = name;
155    m.version = v;
156    m.build = b;
157    m.versions.push(v);
158    m.builds.push(b);
159    m.mainClass = mainClass;
160    // fire the module load listeners
161    for (var i=0;i<ls.length;i=i+1) {
162        ls[i](m);
163    }
164    // label the main class
165    if (mainClass) {
166        mainClass.VERSION = v;
167        mainClass.BUILD = b;
168    } else {
169        YAHOO.log("mainClass is undefined for module " + name, "warn");
170    }
171};
172
173/**
174 * YAHOO.env is used to keep track of what is known about the YUI library and
175 * the browsing environment
176 * @class YAHOO.env
177 * @static
178 */
179YAHOO.env = YAHOO.env || {
180
181    /**
182     * Keeps the version info for all YUI modules that have reported themselves
183     * @property modules
184     * @type Object[]
185     */
186    modules: [],
187    
188    /**
189     * List of functions that should be executed every time a YUI module
190     * reports itself.
191     * @property listeners
192     * @type Function[]
193     */
194    listeners: []
195};
196
197/**
198 * Returns the version data for the specified module:
199 *      <dl>
200 *      <dt>name:</dt>      <dd>The name of the module</dd>
201 *      <dt>version:</dt>   <dd>The version in use</dd>
202 *      <dt>build:</dt>     <dd>The build number in use</dd>
203 *      <dt>versions:</dt>  <dd>All versions that were registered</dd>
204 *      <dt>builds:</dt>    <dd>All builds that were registered.</dd>
205 *      <dt>mainClass:</dt> <dd>An object that was was stamped with the
206 *                 current version and build. If 
207 *                 mainClass.VERSION != version or mainClass.BUILD != build,
208 *                 multiple versions of pieces of the library have been
209 *                 loaded, potentially causing issues.</dd>
210 *       </dl>
211 *
212 * @method getVersion
213 * @static
214 * @param {String}  name the name of the module (event, slider, etc)
215 * @return {Object} The version info
216 */
217YAHOO.env.getVersion = function(name) {
218    return YAHOO.env.modules[name] || null;
219};
220
221/**
222 * Do not fork for a browser if it can be avoided.  Use feature detection when
223 * you can.  Use the user agent as a last resort.  YAHOO.env.ua stores a version
224 * number for the browser engine, 0 otherwise.  This value may or may not map
225 * to the version number of the browser using the engine.  The value is 
226 * presented as a float so that it can easily be used for boolean evaluation 
227 * as well as for looking for a particular range of versions.  Because of this, 
228 * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 
229 * reports 1.8).
230 * @class YAHOO.env.ua
231 * @static
232 */
233YAHOO.env.ua = function() {
234    var o={
235
236        /**
237         * Internet Explorer version number or 0.  Example: 6
238         * @property ie
239         * @type float
240         */
241        ie:0,
242
243        /**
244         * Opera version number or 0.  Example: 9.2
245         * @property opera
246         * @type float
247         */
248        opera:0,
249
250        /**
251         * Gecko engine revision number.  Will evaluate to 1 if Gecko 
252         * is detected but the revision could not be found. Other browsers
253         * will be 0.  Example: 1.8
254         * <pre>
255         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
256         * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8
257         * Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8
258         * Firefox 3 alpha: 1.9a4   <-- Reports 1.9
259         * </pre>
260         * @property gecko
261         * @type float
262         */
263        gecko:0,
264
265        /**
266         * AppleWebKit version.  KHTML browsers that are not WebKit browsers 
267         * will evaluate to 1, other browsers 0.  Example: 418.9.1
268         * <pre>
269         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 
270         *                                   latest available for Mac OSX 10.3.
271         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
272         * Safari 2.0.4:         418     <-- preventDefault fixed
273         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
274         *                                   different versions of webkit
275         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
276         *                                   updated, but not updated
277         *                                   to the latest patch.
278         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native SVG
279         *                                   and many major issues fixed).  
280         * 3.x yahoo.com, flickr:422     <-- Safari 3.x hacks the user agent
281         *                                   string when hitting yahoo.com and 
282         *                                   flickr.com.
283         * Safari 3.0.4 (523.12):523.12  <-- First Tiger release - automatic update
284         *                                   from 2.x via the 10.4.11 OS patch
285         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
286         *                                   yahoo.com user agent hack removed.
287         *                                   
288         * </pre>
289         * http://developer.apple.com/internet/safari/uamatrix.html
290         * @property webkit
291         * @type float
292         */
293        webkit: 0,
294
295        /**
296         * The mobile property will be set to a string containing any relevant
297         * user agent information when a modern mobile browser is detected.
298         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
299         * devices with the WebKit-based browser, and Opera Mini.  
300         * @property mobile 
301         * @type string
302         */
303        mobile: null,
304
305        /**
306         * Adobe AIR version number or 0.  Only populated if webkit is detected.
307         * Example: 1.0
308         * @property air
309         * @type float
310         */
311        air: 0
312
313    };
314
315    var ua=navigator.userAgent, m;
316
317    // Modern KHTML browsers should qualify as Safari X-Grade
318    if ((/KHTML/).test(ua)) {
319        o.webkit=1;
320    }
321    // Modern WebKit browsers are at least X-Grade
322    m=ua.match(/AppleWebKit\/([^\s]*)/);
323    if (m&&m[1]) {
324        o.webkit=parseFloat(m[1]);
325
326        // Mobile browser check
327        if (/ Mobile\//.test(ua)) {
328            o.mobile = "Apple"; // iPhone or iPod Touch
329        } else {
330            m=ua.match(/NokiaN[^\/]*/);
331            if (m) {
332                o.mobile = m[0]; // Nokia N-series, ex: NokiaN95
333            }
334        }
335
336        m=ua.match(/AdobeAIR\/([^\s]*)/);
337        if (m) {
338            o.air = m[0]; // Adobe AIR 1.0 or better
339        }
340
341    }
342
343    if (!o.webkit) { // not webkit
344        // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
345        m=ua.match(/Opera[\s\/]([^\s]*)/);
346        if (m&&m[1]) {
347            o.opera=parseFloat(m[1]);
348            m=ua.match(/Opera Mini[^;]*/);
349            if (m) {
350                o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
351            }
352        } else { // not opera or webkit
353            m=ua.match(/MSIE\s([^;]*)/);
354            if (m&&m[1]) {
355                o.ie=parseFloat(m[1]);
356            } else { // not opera, webkit, or ie
357                m=ua.match(/Gecko\/([^\s]*)/);
358                if (m) {
359                    o.gecko=1; // Gecko detected, look for revision
360                    m=ua.match(/rv:([^\s\)]*)/);
361                    if (m&&m[1]) {
362                        o.gecko=parseFloat(m[1]);
363                    }
364                }
365            }
366        }
367    }
368    
369    return o;
370}();
371
372/*
373 * Initializes the global by creating the default namespaces and applying
374 * any new configuration information that is detected.  This is the setup
375 * for env.
376 * @method init
377 * @static
378 * @private
379 */
380(function() {
381    YAHOO.namespace("util", "widget", "example");
382    if ("undefined" !== typeof YAHOO_config) {
383        var l=YAHOO_config.listener,ls=YAHOO.env.listeners,unique=true,i;
384        if (l) {
385            // if YAHOO is loaded multiple times we need to check to see if
386            // this is a new config object.  If it is, add the new component
387            // load listener to the stack
388            for (i=0;i<ls.length;i=i+1) {
389                if (ls[i]==l) {
390                    unique=false;
391                    break;
392                }
393            }
394            if (unique) {
395                ls.push(l);
396            }
397        }
398    }
399})();
400/**
401 * Provides the language utilites and extensions used by the library
402 * @class YAHOO.lang
403 */
404YAHOO.lang = YAHOO.lang || {
405    /**
406     * Determines whether or not the provided object is an array.
407     * Testing typeof/instanceof/constructor of arrays across frame 
408     * boundaries isn't possible in Safari unless you have a reference
409     * to the other frame to test against its Array prototype.  To
410     * handle this case, we test well-known array properties instead.
411     * properties.
412     * @method isArray
413     * @param {any} o The object being testing
414     * @return {boolean} the result
415     */
416    isArray: function(o) { 
417        if (o) {
418           var l = YAHOO.lang;
419           return l.isNumber(o.length) && l.isFunction(o.splice);
420        }
421        return false;
422    },
423
424    /**
425     * Determines whether or not the provided object is a boolean
426     * @method isBoolean
427     * @param {any} o The object being testing
428     * @return {boolean} the result
429     */
430    isBoolean: function(o) {
431        return typeof o === 'boolean';
432    },
433    
434    /**
435     * Determines whether or not the provided object is a function
436     * @method isFunction
437     * @param {any} o The object being testing
438     * @return {boolean} the result
439     */
440    isFunction: function(o) {
441        return typeof o === 'function';
442    },
443        
444    /**
445     * Determines whether or not the provided object is null
446     * @method isNull
447     * @param {any} o The object being testing
448     * @return {boolean} the result
449     */
450    isNull: function(o) {
451        return o === null;
452    },
453        
454    /**
455     * Determines whether or not the provided object is a legal number
456     * @method isNumber
457     * @param {any} o The object being testing
458     * @return {boolean} the result
459     */
460    isNumber: function(o) {
461        return typeof o === 'number' && isFinite(o);
462    },
463      
464    /**
465     * Determines whether or not the provided object is of type object
466     * or function
467     * @method isObject
468     * @param {any} o The object being testing
469     * @return {boolean} the result
470     */  
471    isObject: function(o) {
472return (o && (typeof o === 'object' || YAHOO.lang.isFunction(o))) || false;
473    },
474        
475    /**
476     * Determines whether or not the provided object is a string
477     * @method isString
478     * @param {any} o The object being testing
479     * @return {boolean} the result
480     */
481    isString: function(o) {
482        return typeof o === 'string';
483    },
484        
485    /**
486     * Determines whether or not the provided object is undefined
487     * @method isUndefined
488     * @param {any} o The object being testing
489     * @return {boolean} the result
490     */
491    isUndefined: function(o) {
492        return typeof o === 'undefined';
493    },
494    
495    /**
496     * Determines whether or not the property was added
497     * to the object instance.  Returns false if the property is not present
498     * in the object, or was inherited from the prototype.
499     * This abstraction is provided to enable hasOwnProperty for Safari 1.3.x.
500     * There is a discrepancy between YAHOO.lang.hasOwnProperty and
501     * Object.prototype.hasOwnProperty when the property is a primitive added to
502     * both the instance AND prototype with the same value:
503     * <pre>
504     * var A = function() {};
505     * A.prototype.foo = 'foo';
506     * var a = new A();
507     * a.foo = 'foo';
508     * alert(a.hasOwnProperty('foo')); // true
509     * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback
510     * </pre>
511     * @method hasOwnProperty
512     * @param {any} o The object being testing
513     * @return {boolean} the result
514     */
515    hasOwnProperty: function(o, prop) {
516        if (Object.prototype.hasOwnProperty) {
517            return o.hasOwnProperty(prop);
518        }
519        
520        return !YAHOO.lang.isUndefined(o[prop]) && 
521                o.constructor.prototype[prop] !== o[prop];
522    },
523 
524    /**
525     * IE will not enumerate native functions in a derived object even if the
526     * function was overridden.  This is a workaround for specific functions 
527     * we care about on the Object prototype. 
528     * @property _IEEnumFix
529     * @param {Function} r  the object to receive the augmentation
530     * @param {Function} s  the object that supplies the properties to augment
531     * @static
532     * @private
533     */
534    _IEEnumFix: function(r, s) {
535        if (YAHOO.env.ua.ie) {
536            var add=["toString", "valueOf"], i;
537            for (i=0;i<add.length;i=i+1) {
538                var fname=add[i],f=s[fname];
539                if (YAHOO.lang.isFunction(f) && f!=Object.prototype[fname]) {
540                    r[fname]=f;
541                }
542            }
543        }
544    },
545       
546    /**
547     * Utility to set up the prototype, constructor and superclass properties to
548     * support an inheritance strategy that can chain constructors and methods.
549     * Static members will not be inherited.
550     *
551     * @method extend
552     * @static
553     * @param {Function} subc   the object to modify
554     * @param {Function} superc the object to inherit
555     * @param {Object} overrides  additional properties/methods to add to the
556     *                              subclass prototype.  These will override the
557     *                              matching items obtained from the superclass 
558     *                              if present.
559     */
560    extend: function(subc, superc, overrides) {
561        if (!superc||!subc) {
562            throw new Error("YAHOO.lang.extend failed, please check that " +
563                            "all dependencies are included.");
564        }
565        var F = function() {};
566        F.prototype=superc.prototype;
567        subc.prototype=new F();
568        subc.prototype.constructor=subc;
569        subc.superclass=superc.prototype;
570        if (superc.prototype.constructor == Object.prototype.constructor) {
571            superc.prototype.constructor=superc;
572        }
573    
574        if (overrides) {
575            for (var i in overrides) {
576                subc.prototype[i]=overrides[i];
577            }
578
579            YAHOO.lang._IEEnumFix(subc.prototype, overrides);
580        }
581    },
582   
583    /**
584     * Applies all properties in the supplier to the receiver if the
585     * receiver does not have these properties yet.  Optionally, one or 
586     * more methods/properties can be specified (as additional 
587     * parameters).  This option will overwrite the property if receiver 
588     * has it already.  If true is passed as the third parameter, all 
589     * properties will be applied and _will_ overwrite properties in 
590     * the receiver.
591     *
592     * @method augmentObject
593     * @static
594     * @since 2.3.0
595     * @param {Function} r  the object to receive the augmentation
596     * @param {Function} s  the object that supplies the properties to augment
597     * @param {String*|boolean}  arguments zero or more properties methods 
598     *        to augment the receiver with.  If none specified, everything
599     *        in the supplier will be used unless it would
600     *        overwrite an existing property in the receiver. If true
601     *        is specified as the third parameter, all properties will
602     *        be applied and will overwrite an existing property in
603     *        the receiver
604     */
605    augmentObject: function(r, s) {
606        if (!s||!r) {
607            throw new Error("Absorb failed, verify dependencies.");
608        }
609        var a=arguments, i, p, override=a[2];
610        if (override && override!==true) { // only absorb the specified properties
611            for (i=2; i<a.length; i=i+1) {
612                r[a[i]] = s[a[i]];
613            }
614        } else { // take everything, overwriting only if the third parameter is true
615            for (p in s) { 
616                if (override || !r[p]) {
617                    r[p] = s[p];
618                }
619            }
620            
621            YAHOO.lang._IEEnumFix(r, s);
622        }
623    },
624 
625    /**
626     * Same as YAHOO.lang.augmentObject, except it only applies prototype properties
627     * @see YAHOO.lang.augmentObject
628     * @method augmentProto
629     * @static
630     * @param {Function} r  the object to receive the augmentation
631     * @param {Function} s  the object that supplies the properties to augment
632     * @param {String*|boolean}  arguments zero or more properties methods 
633     *        to augment the receiver with.  If none specified, everything 
634     *        in the supplier will be used unless it would overwrite an existing 
635     *        property in the receiver.  if true is specified as the third 
636     *        parameter, all properties will be applied and will overwrite an 
637     *        existing property in the receiver
638     */
639    augmentProto: function(r, s) {
640        if (!s||!r) {
641            throw new Error("Augment failed, verify dependencies.");
642        }
643        //var a=[].concat(arguments);
644        var a=[r.prototype,s.prototype];
645        for (var i=2;i<arguments.length;i=i+1) {
646            a.push(arguments[i]);
647        }
648        YAHOO.lang.augmentObject.apply(this, a);
649    },
650
651      
652    /**
653     * Returns a simple string representation of the object or array.
654     * Other types of objects will be returned unprocessed.  Arrays
655     * are expected to be indexed.  Use object notation for
656     * associative arrays.
657     * @method dump
658     * @since 2.3.0
659     * @param o {Object} The object to dump
660     * @param d {int} How deep to recurse child objects, default 3
661     * @return {String} the dump result
662     */
663    dump: function(o, d) {
664        var l=YAHOO.lang,i,len,s=[],OBJ="{...}",FUN="f(){...}",
665            COMMA=', ', ARROW=' => ';
666
667        // Cast non-objects to string
668        // Skip dates because the std toString is what we want
669        // Skip HTMLElement-like objects because trying to dump 
670        // an element will cause an unhandled exception in FF 2.x
671        if (!l.isObject(o)) {
672            return o + "";
673        } else if (o instanceof Date || ("nodeType" in o && "tagName" in o)) {
674            return o;
675        } else if  (l.isFunction(o)) {
676            return FUN;
677        }
678
679        // dig into child objects the depth specifed. Default 3
680        d = (l.isNumber(d)) ? d : 3;
681
682        // arrays [1, 2, 3]
683        if (l.isArray(o)) {
684            s.push("[");
685            for (i=0,len=o.length;i<len;i=i+1) {
686                if (l.isObject(o[i])) {
687                    s.push((d > 0) ? l.dump(o[i], d-1) : OBJ);
688                } else {
689                    s.push(o[i]);
690                }
691                s.push(COMMA);
692            }
693            if (s.length > 1) {
694                s.pop();
695            }
696            s.push("]");
697        // objects {k1 => v1, k2 => v2}
698        } else {
699            s.push("{");
700            for (i in o) {
701                if (l.hasOwnProperty(o, i)) {
702                    s.push(i + ARROW);
703                    if (l.isObject(o[i])) {
704                        s.push((d > 0) ? l.dump(o[i], d-1) : OBJ);
705                    } else {
706                        s.push(o[i]);
707                    }
708                    s.push(COMMA);
709                }
710            }
711            if (s.length > 1) {
712                s.pop();
713            }
714            s.push("}");
715        }
716
717        return s.join("");
718    },
719
720    /**
721     * Does variable substitution on a string. It scans through the string 
722     * looking for expressions enclosed in { } braces. If an expression 
723     * is found, it is used a key on the object.  If there is a space in
724     * the key, the first word is used for the key and the rest is provided
725     * to an optional function to be used to programatically determine the
726     * value (the extra information might be used for this decision). If 
727     * the value for the key in the object, or what is returned from the
728     * function has a string value, number value, or object value, it is 
729     * substituted for the bracket expression and it repeats.  If this
730     * value is an object, it uses the Object's toString() if this has
731     * been overridden, otherwise it does a shallow dump of the key/value
732     * pairs.
733     * @method substitute
734     * @since 2.3.0
735     * @param s {String} The string that will be modified.
736     * @param o {Object} An object containing the replacement values
737     * @param f {Function} An optional function that can be used to
738     *                     process each match.  It receives the key,
739     *                     value, and any extra metadata included with
740     *                     the key inside of the braces.
741     * @return {String} the substituted string
742     */
743    substitute: function (s, o, f) {
744        var i, j, k, key, v, meta, l=YAHOO.lang, saved=[], token, 
745            DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}';
746
747
748        for (;;) {
749            i = s.lastIndexOf(LBRACE);
750            if (i < 0) {
751                break;
752            }
753            j = s.indexOf(RBRACE, i);
754            if (i + 1 >= j) {
755                break;
756            }
757
758            //Extract key and meta info 
759            token = s.substring(i + 1, j);
760            key = token;
761            meta = null;
762            k = key.indexOf(SPACE);
763            if (k > -1) {
764                meta = key.substring(k + 1);
765                key = key.substring(0, k);
766            }
767
768            // lookup the value
769            v = o[key];
770
771            // if a substitution function was provided, execute it
772            if (f) {
773                v = f(key, v, meta);
774            }
775
776            if (l.isObject(v)) {
777                if (l.isArray(v)) {
778                    v = l.dump(v, parseInt(meta, 10));
779                } else {
780                    meta = meta || "";
781
782                    // look for the keyword 'dump', if found force obj dump
783                    var dump = meta.indexOf(DUMP);
784                    if (dump > -1) {
785                        meta = meta.substring(4);
786                    }
787
788                    // use the toString if it is not the Object toString 
789                    // and the 'dump' meta info was not found
790                    if (v.toString===Object.prototype.toString||dump>-1) {
791                        v = l.dump(v, parseInt(meta, 10));
792                    } else {
793                        v = v.toString();
794                    }
795                }
796            } else if (!l.isString(v) && !l.isNumber(v)) {
797                // This {block} has no replace string. Save it for later.
798                v = "~-" + saved.length + "-~";
799                saved[saved.length] = token;
800
801                // break;
802            }
803
804            s = s.substring(0, i) + v + s.substring(j + 1);
805
806
807        }
808
809        // restore saved {block}s
810        for (i=saved.length-1; i>=0; i=i-1) {
811            s = s.replace(new RegExp("~-" + i + "-~"), "{"  + saved[i] + "}", "g");
812        }
813
814        return s;
815    },
816
817
818    /**
819     * Returns a string without any leading or trailing whitespace.  If 
820     * the input is not a string, the input will be returned untouched.
821     * @method trim
822     * @since 2.3.0
823     * @param s {string} the string to trim
824     * @return {string} the trimmed string
825     */
826    trim: function(s){
827        try {
828            return s.replace(/^\s+|\s+$/g, "");
829        } catch(e) {
830            return s;
831        }
832    },
833
834    /**
835     * Returns a new object containing all of the properties of
836     * all the supplied objects.  The properties from later objects
837     * will overwrite those in earlier objects.
838     * @method merge
839     * @since 2.3.0
840     * @param arguments {Object*} the objects to merge
841     * @return the new merged object
842     */
843    merge: function() {
844        var o={}, a=arguments;
845        for (var i=0, l=a.length; i<l; i=i+1) {
846            YAHOO.lang.augmentObject(o, a[i], true);
847        }
848        return o;
849    },
850
851    /**
852     * Executes the supplied function in the context of the supplied 
853     * object 'when' milliseconds later.  Executes the function a 
854     * single time unless periodic is set to true.
855     * @method later
856     * @since 2.4.0
857     * @param when {int} the number of milliseconds to wait until the fn 
858     * is executed
859     * @param o the context object
860     * @param fn {Function|String} the function to execute or the name of 
861     * the method in the 'o' object to execute
862     * @param data [Array] data that is provided to the function.  This accepts
863     * either a single item or an array.  If an array is provided, the
864     * function is executed with one parameter for each array item.  If
865     * you need to pass a single array parameter, it needs to be wrapped in
866     * an array [myarray]
867     * @param periodic {boolean} if true, executes continuously at supplied 
868     * interval until canceled
869     * @return a timer object. Call the cancel() method on this object to 
870     * stop the timer.
871     */
872    later: function(when, o, fn, data, periodic) {
873        when = when || 0; 
874        o = o || {};
875        var m=fn, d=data, f, r;
876
877        if (YAHOO.lang.isString(fn)) {
878            m = o[fn];
879        }
880
881        if (!m) {
882            throw new TypeError("method undefined");
883        }
884
885        if (!YAHOO.lang.isArray(d)) {
886            d = [data];
887        }
888
889        f = function() {
890            m.apply(o, d);
891        };
892
893        r = (periodic) ? setInterval(f, when) : setTimeout(f, when);
894
895        return {
896            interval: periodic,
897            cancel: function() {
898                if (this.interval) {
899                    clearInterval(r);
900                } else {
901                    clearTimeout(r);
902                }
903            }
904        };
905    },
906    
907    /**
908     * A convenience method for detecting a legitimate non-null value.
909     * Returns false for null/undefined/NaN, true for other values, 
910     * including 0/false/''
911     * @method isValue
912     * @since 2.3.0
913     * @param o {any} the item to test
914     * @return {boolean} true if it is not null/undefined/NaN || false
915     */
916    isValue: function(o) {
917        // return (o || o === false || o === 0 || o === ''); // Infinity fails
918        var l = YAHOO.lang;
919return (l.isObject(o) || l.isString(o) || l.isNumber(o) || l.isBoolean(o));
920    }
921
922};
923
924/*
925 * An alias for <a href="YAHOO.lang.html">YAHOO.lang</a>
926 * @class YAHOO.util.Lang
927 */
928YAHOO.util.Lang = YAHOO.lang;
929 
930/**
931 * Same as YAHOO.lang.augmentObject, except it only applies prototype 
932 * properties.  This is an alias for augmentProto.
933 * @see YAHOO.lang.augmentObject
934 * @method augment
935 * @static
936 * @param {Function} r  the object to receive the augmentation
937 * @param {Function} s  the object that supplies the properties to augment
938 * @param {String*|boolean}  arguments zero or more properties methods to 
939 *        augment the receiver with.  If none specified, everything
940 *        in the supplier will be used unless it would
941 *        overwrite an existing property in the receiver.  if true
942 *        is specified as the third parameter, all properties will
943 *        be applied and will overwrite an existing property in
944 *        the receiver
945 */
946YAHOO.lang.augment = YAHOO.lang.augmentProto;
947
948/**
949 * An alias for <a href="YAHOO.lang.html#augment">YAHOO.lang.augment</a>
950 * @for YAHOO
951 * @method augment
952 * @static
953 * @param {Function} r  the object to receive the augmentation
954 * @param {Function} s  the object that supplies the properties to augment
955 * @param {String*}  arguments zero or more properties methods to 
956 *        augment the receiver with.  If none specified, everything
957 *        in the supplier will be used unless it would
958 *        overwrite an existing property in the receiver
959 */
960YAHOO.augment = YAHOO.lang.augmentProto;
961       
962/**
963 * An alias for <a href="YAHOO.lang.html#extend">YAHOO.lang.extend</a>
964 * @method extend
965 * @static
966 * @param {Function} subc   the object to modify
967 * @param {Function} superc the object to inherit
968 * @param {Object} overrides  additional properties/methods to add to the
969 *        subclass prototype.  These will override the
970 *        matching items obtained from the superclass if present.
971 */
972YAHOO.extend = YAHOO.lang.extend;
973
974YAHOO.register("yahoo", YAHOO, {version: "2.5.1", build: "984"});