Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / test / data / dromaeo / lib / yahoo.js
blob92ba86582418674b5057a57daf9017ad92437da6
1 /*
2 Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.6.0
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  */
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  */
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  */
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  */
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  */
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  */
64 if (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 = {};
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  */
96 YAHOO.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;
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     }
109     return o;
113  * Uses YAHOO.widget.Logger to output a log message, if the widget is
114  * available.
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  */
125 YAHOO.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     }
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  */
148 YAHOO.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     }
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  */
179 YAHOO.env = YAHOO.env || {
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: []
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>
212  * @method getVersion
213  * @static
214  * @param {String}  name the name of the module (event, slider, etc)
215  * @return {Object} The version info
216  */
217 YAHOO.env.getVersion = function(name) {
218     return YAHOO.env.modules[name] || null;
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  */
233 YAHOO.env.ua = function() {
234     var o={
236         /**
237          * Internet Explorer version number or 0.  Example: 6
238          * @property ie
239          * @type float
240          */
241         ie:0,
243         /**
244          * Opera version number or 0.  Example: 9.2
245          * @property opera
246          * @type float
247          */
248         opera:0,
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,
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,
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,
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
313     };
315     var ua=navigator.userAgent, m;
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]);
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         }
336         m=ua.match(/AdobeAIR\/([^\s]*)/);
337         if (m) {
338             o.air = m[0]; // Adobe AIR 1.0 or better
339         }
341     }
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 }();
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 })();
401  * Provides the language utilites and extensions used by the library
402  * @class YAHOO.lang
403  */
404 YAHOO.lang = YAHOO.lang || {};
406 (function() {
408 var L = YAHOO.lang,
410     // ADD = ["toString", "valueOf", "hasOwnProperty"],
411     ADD = ["toString", "valueOf"],
413     OB = {
415     /**
416      * Determines whether or not the provided object is an array.
417      * Testing typeof/instanceof/constructor of arrays across frame 
418      * boundaries isn't possible in Safari unless you have a reference
419      * to the other frame to test against its Array prototype.  To
420      * handle this case, we test well-known array properties instead.
421      * properties.
422      * @method isArray
423      * @param {any} o The object being testing
424      * @return {boolean} the result
425      */
426     isArray: function(o) { 
427         if (o) {
428            return L.isNumber(o.length) && L.isFunction(o.splice);
429         }
430         return false;
431     },
433     /**
434      * Determines whether or not the provided object is a boolean
435      * @method isBoolean
436      * @param {any} o The object being testing
437      * @return {boolean} the result
438      */
439     isBoolean: function(o) {
440         return typeof o === 'boolean';
441     },
442     
443     /**
444      * Determines whether or not the provided object is a function
445      * @method isFunction
446      * @param {any} o The object being testing
447      * @return {boolean} the result
448      */
449     isFunction: function(o) {
450         return typeof o === 'function';
451     },
452         
453     /**
454      * Determines whether or not the provided object is null
455      * @method isNull
456      * @param {any} o The object being testing
457      * @return {boolean} the result
458      */
459     isNull: function(o) {
460         return o === null;
461     },
462         
463     /**
464      * Determines whether or not the provided object is a legal number
465      * @method isNumber
466      * @param {any} o The object being testing
467      * @return {boolean} the result
468      */
469     isNumber: function(o) {
470         return typeof o === 'number' && isFinite(o);
471     },
472       
473     /**
474      * Determines whether or not the provided object is of type object
475      * or function
476      * @method isObject
477      * @param {any} o The object being testing
478      * @return {boolean} the result
479      */  
480     isObject: function(o) {
481 return (o && (typeof o === 'object' || L.isFunction(o))) || false;
482     },
483         
484     /**
485      * Determines whether or not the provided object is a string
486      * @method isString
487      * @param {any} o The object being testing
488      * @return {boolean} the result
489      */
490     isString: function(o) {
491         return typeof o === 'string';
492     },
493         
494     /**
495      * Determines whether or not the provided object is undefined
496      * @method isUndefined
497      * @param {any} o The object being testing
498      * @return {boolean} the result
499      */
500     isUndefined: function(o) {
501         return typeof o === 'undefined';
502     },
503     
505     /**
506      * IE will not enumerate native functions in a derived object even if the
507      * function was overridden.  This is a workaround for specific functions 
508      * we care about on the Object prototype. 
509      * @property _IEEnumFix
510      * @param {Function} r  the object to receive the augmentation
511      * @param {Function} s  the object that supplies the properties to augment
512      * @static
513      * @private
514      */
515     _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) {
516             for (var i=0;i<ADD.length;i=i+1) {
517                 var fname=ADD[i],f=s[fname];
518                 if (L.isFunction(f) && f!=Object.prototype[fname]) {
519                     r[fname]=f;
520                 }
521             }
522     } : function(){},
523        
524     /**
525      * Utility to set up the prototype, constructor and superclass properties to
526      * support an inheritance strategy that can chain constructors and methods.
527      * Static members will not be inherited.
528      *
529      * @method extend
530      * @static
531      * @param {Function} subc   the object to modify
532      * @param {Function} superc the object to inherit
533      * @param {Object} overrides  additional properties/methods to add to the
534      *                              subclass prototype.  These will override the
535      *                              matching items obtained from the superclass 
536      *                              if present.
537      */
538     extend: function(subc, superc, overrides) {
539         if (!superc||!subc) {
540             throw new Error("extend failed, please check that " +
541                             "all dependencies are included.");
542         }
543         var F = function() {};
544         F.prototype=superc.prototype;
545         subc.prototype=new F();
546         subc.prototype.constructor=subc;
547         subc.superclass=superc.prototype;
548         if (superc.prototype.constructor == Object.prototype.constructor) {
549             superc.prototype.constructor=superc;
550         }
551     
552         if (overrides) {
553             for (var i in overrides) {
554                 if (L.hasOwnProperty(overrides, i)) {
555                     subc.prototype[i]=overrides[i];
556                 }
557             }
559             L._IEEnumFix(subc.prototype, overrides);
560         }
561     },
562    
563     /**
564      * Applies all properties in the supplier to the receiver if the
565      * receiver does not have these properties yet.  Optionally, one or 
566      * more methods/properties can be specified (as additional 
567      * parameters).  This option will overwrite the property if receiver 
568      * has it already.  If true is passed as the third parameter, all 
569      * properties will be applied and _will_ overwrite properties in 
570      * the receiver.
571      *
572      * @method augmentObject
573      * @static
574      * @since 2.3.0
575      * @param {Function} r  the object to receive the augmentation
576      * @param {Function} s  the object that supplies the properties to augment
577      * @param {String*|boolean}  arguments zero or more properties methods 
578      *        to augment the receiver with.  If none specified, everything
579      *        in the supplier will be used unless it would
580      *        overwrite an existing property in the receiver. If true
581      *        is specified as the third parameter, all properties will
582      *        be applied and will overwrite an existing property in
583      *        the receiver
584      */
585     augmentObject: function(r, s) {
586         if (!s||!r) {
587             throw new Error("Absorb failed, verify dependencies.");
588         }
589         var a=arguments, i, p, override=a[2];
590         if (override && override!==true) { // only absorb the specified properties
591             for (i=2; i<a.length; i=i+1) {
592                 r[a[i]] = s[a[i]];
593             }
594         } else { // take everything, overwriting only if the third parameter is true
595             for (p in s) { 
596                 if (override || !(p in r)) {
597                     r[p] = s[p];
598                 }
599             }
600             
601             L._IEEnumFix(r, s);
602         }
603     },
605     /**
606      * Same as YAHOO.lang.augmentObject, except it only applies prototype properties
607      * @see YAHOO.lang.augmentObject
608      * @method augmentProto
609      * @static
610      * @param {Function} r  the object to receive the augmentation
611      * @param {Function} s  the object that supplies the properties to augment
612      * @param {String*|boolean}  arguments zero or more properties methods 
613      *        to augment the receiver with.  If none specified, everything 
614      *        in the supplier will be used unless it would overwrite an existing 
615      *        property in the receiver.  if true is specified as the third 
616      *        parameter, all properties will be applied and will overwrite an 
617      *        existing property in the receiver
618      */
619     augmentProto: function(r, s) {
620         if (!s||!r) {
621             throw new Error("Augment failed, verify dependencies.");
622         }
623         //var a=[].concat(arguments);
624         var a=[r.prototype,s.prototype];
625         for (var i=2;i<arguments.length;i=i+1) {
626             a.push(arguments[i]);
627         }
628         L.augmentObject.apply(this, a);
629     },
631       
632     /**
633      * Returns a simple string representation of the object or array.
634      * Other types of objects will be returned unprocessed.  Arrays
635      * are expected to be indexed.  Use object notation for
636      * associative arrays.
637      * @method dump
638      * @since 2.3.0
639      * @param o {Object} The object to dump
640      * @param d {int} How deep to recurse child objects, default 3
641      * @return {String} the dump result
642      */
643     dump: function(o, d) {
644         var i,len,s=[],OBJ="{...}",FUN="f(){...}",
645             COMMA=', ', ARROW=' => ';
647         // Cast non-objects to string
648         // Skip dates because the std toString is what we want
649         // Skip HTMLElement-like objects because trying to dump 
650         // an element will cause an unhandled exception in FF 2.x
651         if (!L.isObject(o)) {
652             return o + "";
653         } else if (o instanceof Date || ("nodeType" in o && "tagName" in o)) {
654             return o;
655         } else if  (L.isFunction(o)) {
656             return FUN;
657         }
659         // dig into child objects the depth specifed. Default 3
660         d = (L.isNumber(d)) ? d : 3;
662         // arrays [1, 2, 3]
663         if (L.isArray(o)) {
664             s.push("[");
665             for (i=0,len=o.length;i<len;i=i+1) {
666                 if (L.isObject(o[i])) {
667                     s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
668                 } else {
669                     s.push(o[i]);
670                 }
671                 s.push(COMMA);
672             }
673             if (s.length > 1) {
674                 s.pop();
675             }
676             s.push("]");
677         // objects {k1 => v1, k2 => v2}
678         } else {
679             s.push("{");
680             for (i in o) {
681                 if (L.hasOwnProperty(o, i)) {
682                     s.push(i + ARROW);
683                     if (L.isObject(o[i])) {
684                         s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
685                     } else {
686                         s.push(o[i]);
687                     }
688                     s.push(COMMA);
689                 }
690             }
691             if (s.length > 1) {
692                 s.pop();
693             }
694             s.push("}");
695         }
697         return s.join("");
698     },
700     /**
701      * Does variable substitution on a string. It scans through the string 
702      * looking for expressions enclosed in { } braces. If an expression 
703      * is found, it is used a key on the object.  If there is a space in
704      * the key, the first word is used for the key and the rest is provided
705      * to an optional function to be used to programatically determine the
706      * value (the extra information might be used for this decision). If 
707      * the value for the key in the object, or what is returned from the
708      * function has a string value, number value, or object value, it is 
709      * substituted for the bracket expression and it repeats.  If this
710      * value is an object, it uses the Object's toString() if this has
711      * been overridden, otherwise it does a shallow dump of the key/value
712      * pairs.
713      * @method substitute
714      * @since 2.3.0
715      * @param s {String} The string that will be modified.
716      * @param o {Object} An object containing the replacement values
717      * @param f {Function} An optional function that can be used to
718      *                     process each match.  It receives the key,
719      *                     value, and any extra metadata included with
720      *                     the key inside of the braces.
721      * @return {String} the substituted string
722      */
723     substitute: function (s, o, f) {
724         var i, j, k, key, v, meta, saved=[], token, 
725             DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}';
728         for (;;) {
729             i = s.lastIndexOf(LBRACE);
730             if (i < 0) {
731                 break;
732             }
733             j = s.indexOf(RBRACE, i);
734             if (i + 1 >= j) {
735                 break;
736             }
738             //Extract key and meta info 
739             token = s.substring(i + 1, j);
740             key = token;
741             meta = null;
742             k = key.indexOf(SPACE);
743             if (k > -1) {
744                 meta = key.substring(k + 1);
745                 key = key.substring(0, k);
746             }
748             // lookup the value
749             v = o[key];
751             // if a substitution function was provided, execute it
752             if (f) {
753                 v = f(key, v, meta);
754             }
756             if (L.isObject(v)) {
757                 if (L.isArray(v)) {
758                     v = L.dump(v, parseInt(meta, 10));
759                 } else {
760                     meta = meta || "";
762                     // look for the keyword 'dump', if found force obj dump
763                     var dump = meta.indexOf(DUMP);
764                     if (dump > -1) {
765                         meta = meta.substring(4);
766                     }
768                     // use the toString if it is not the Object toString 
769                     // and the 'dump' meta info was not found
770                     if (v.toString===Object.prototype.toString||dump>-1) {
771                         v = L.dump(v, parseInt(meta, 10));
772                     } else {
773                         v = v.toString();
774                     }
775                 }
776             } else if (!L.isString(v) && !L.isNumber(v)) {
777                 // This {block} has no replace string. Save it for later.
778                 v = "~-" + saved.length + "-~";
779                 saved[saved.length] = token;
781                 // break;
782             }
784             s = s.substring(0, i) + v + s.substring(j + 1);
787         }
789         // restore saved {block}s
790         for (i=saved.length-1; i>=0; i=i-1) {
791             s = s.replace(new RegExp("~-" + i + "-~"), "{"  + saved[i] + "}", "g");
792         }
794         return s;
795     },
798     /**
799      * Returns a string without any leading or trailing whitespace.  If 
800      * the input is not a string, the input will be returned untouched.
801      * @method trim
802      * @since 2.3.0
803      * @param s {string} the string to trim
804      * @return {string} the trimmed string
805      */
806     trim: function(s){
807         try {
808             return s.replace(/^\s+|\s+$/g, "");
809         } catch(e) {
810             return s;
811         }
812     },
814     /**
815      * Returns a new object containing all of the properties of
816      * all the supplied objects.  The properties from later objects
817      * will overwrite those in earlier objects.
818      * @method merge
819      * @since 2.3.0
820      * @param arguments {Object*} the objects to merge
821      * @return the new merged object
822      */
823     merge: function() {
824         var o={}, a=arguments;
825         for (var i=0, l=a.length; i<l; i=i+1) {
826             L.augmentObject(o, a[i], true);
827         }
828         return o;
829     },
831     /**
832      * Executes the supplied function in the context of the supplied 
833      * object 'when' milliseconds later.  Executes the function a 
834      * single time unless periodic is set to true.
835      * @method later
836      * @since 2.4.0
837      * @param when {int} the number of milliseconds to wait until the fn 
838      * is executed
839      * @param o the context object
840      * @param fn {Function|String} the function to execute or the name of 
841      * the method in the 'o' object to execute
842      * @param data [Array] data that is provided to the function.  This accepts
843      * either a single item or an array.  If an array is provided, the
844      * function is executed with one parameter for each array item.  If
845      * you need to pass a single array parameter, it needs to be wrapped in
846      * an array [myarray]
847      * @param periodic {boolean} if true, executes continuously at supplied 
848      * interval until canceled
849      * @return a timer object. Call the cancel() method on this object to 
850      * stop the timer.
851      */
852     later: function(when, o, fn, data, periodic) {
853         when = when || 0; 
854         o = o || {};
855         var m=fn, d=data, f, r;
857         if (L.isString(fn)) {
858             m = o[fn];
859         }
861         if (!m) {
862             throw new TypeError("method undefined");
863         }
865         if (!L.isArray(d)) {
866             d = [data];
867         }
869         f = function() {
870             m.apply(o, d);
871         };
873         r = (periodic) ? setInterval(f, when) : setTimeout(f, when);
875         return {
876             interval: periodic,
877             cancel: function() {
878                 if (this.interval) {
879                     clearInterval(r);
880                 } else {
881                     clearTimeout(r);
882                 }
883             }
884         };
885     },
886     
887     /**
888      * A convenience method for detecting a legitimate non-null value.
889      * Returns false for null/undefined/NaN, true for other values, 
890      * including 0/false/''
891      * @method isValue
892      * @since 2.3.0
893      * @param o {any} the item to test
894      * @return {boolean} true if it is not null/undefined/NaN || false
895      */
896     isValue: function(o) {
897         // return (o || o === false || o === 0 || o === ''); // Infinity fails
898 return (L.isObject(o) || L.isString(o) || L.isNumber(o) || L.isBoolean(o));
899     }
904  * Determines whether or not the property was added
905  * to the object instance.  Returns false if the property is not present
906  * in the object, or was inherited from the prototype.
907  * This abstraction is provided to enable hasOwnProperty for Safari 1.3.x.
908  * There is a discrepancy between YAHOO.lang.hasOwnProperty and
909  * Object.prototype.hasOwnProperty when the property is a primitive added to
910  * both the instance AND prototype with the same value:
911  * <pre>
912  * var A = function() {};
913  * A.prototype.foo = 'foo';
914  * var a = new A();
915  * a.foo = 'foo';
916  * alert(a.hasOwnProperty('foo')); // true
917  * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback
918  * </pre>
919  * @method hasOwnProperty
920  * @param {any} o The object being testing
921  * @param prop {string} the name of the property to test
922  * @return {boolean} the result
923  */
924 L.hasOwnProperty = (Object.prototype.hasOwnProperty) ?
925     function(o, prop) {
926         return o && o.hasOwnProperty(prop);
927     } : function(o, prop) {
928         return !L.isUndefined(o[prop]) && 
929                 o.constructor.prototype[prop] !== o[prop];
930     };
932 // new lang wins
933 OB.augmentObject(L, OB, true);
936  * An alias for <a href="YAHOO.lang.html">YAHOO.lang</a>
937  * @class YAHOO.util.Lang
938  */
939 YAHOO.util.Lang = L;
942  * Same as YAHOO.lang.augmentObject, except it only applies prototype 
943  * properties.  This is an alias for augmentProto.
944  * @see YAHOO.lang.augmentObject
945  * @method augment
946  * @static
947  * @param {Function} r  the object to receive the augmentation
948  * @param {Function} s  the object that supplies the properties to augment
949  * @param {String*|boolean}  arguments zero or more properties methods to 
950  *        augment the receiver with.  If none specified, everything
951  *        in the supplier will be used unless it would
952  *        overwrite an existing property in the receiver.  if true
953  *        is specified as the third parameter, all properties will
954  *        be applied and will overwrite an existing property in
955  *        the receiver
956  */
957 L.augment = L.augmentProto;
960  * An alias for <a href="YAHOO.lang.html#augment">YAHOO.lang.augment</a>
961  * @for YAHOO
962  * @method augment
963  * @static
964  * @param {Function} r  the object to receive the augmentation
965  * @param {Function} s  the object that supplies the properties to augment
966  * @param {String*}  arguments zero or more properties methods to 
967  *        augment the receiver with.  If none specified, everything
968  *        in the supplier will be used unless it would
969  *        overwrite an existing property in the receiver
970  */
971 YAHOO.augment = L.augmentProto;
972        
974  * An alias for <a href="YAHOO.lang.html#extend">YAHOO.lang.extend</a>
975  * @method extend
976  * @static
977  * @param {Function} subc   the object to modify
978  * @param {Function} superc the object to inherit
979  * @param {Object} overrides  additional properties/methods to add to the
980  *        subclass prototype.  These will override the
981  *        matching items obtained from the superclass if present.
982  */
983 YAHOO.extend = L.extend;
985 })();
986 YAHOO.register("yahoo", YAHOO, {version: "2.6.0", build: "1321"});