Project

General

Profile

1
/*
2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
5
version: 2.8.0r4
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

    
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 = {};
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
 * For implementation code that uses YUI, do not create your components
92
 * in the namespaces defined by YUI (
93
 * <code>YAHOO.util</code>, 
94
 * <code>YAHOO.widget</code>, 
95
 * <code>YAHOO.lang</code>, 
96
 * <code>YAHOO.tool</code>, 
97
 * <code>YAHOO.example</code>, 
98
 * <code>YAHOO.env</code>) -- create your own namespace (e.g., 'companyname').
99
 *
100
 * @method namespace
101
 * @static
102
 * @param  {String*} arguments 1-n namespaces to create 
103
 * @return {Object}  A reference to the last namespace object created
104
 */
105
YAHOO.namespace = function() {
106
    var a=arguments, o=null, i, j, d;
107
    for (i=0; i<a.length; i=i+1) {
108
        d=(""+a[i]).split(".");
109
        o=YAHOO;
110

    
111
        // YAHOO is implied, so it is ignored if it is included
112
        for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
113
            o[d[j]]=o[d[j]] || {};
114
            o=o[d[j]];
115
        }
116
    }
117

    
118
    return o;
119
};
120

    
121
/**
122
 * Uses YAHOO.widget.Logger to output a log message, if the widget is
123
 * available.
124
 *
125
 * @method log
126
 * @static
127
 * @param  {String}  msg  The message to log.
128
 * @param  {String}  cat  The log category for the message.  Default
129
 *                        categories are "info", "warn", "error", time".
130
 *                        Custom categories can be used as well. (opt)
131
 * @param  {String}  src  The source of the the message (opt)
132
 * @return {Boolean}      True if the log operation was successful.
133
 */
134
YAHOO.log = function(msg, cat, src) {
135
    var l=YAHOO.widget.Logger;
136
    if(l && l.log) {
137
        return l.log(msg, cat, src);
138
    } else {
139
        return false;
140
    }
141
};
142

    
143
/**
144
 * Registers a module with the YAHOO object
145
 * @method register
146
 * @static
147
 * @param {String}   name    the name of the module (event, slider, etc)
148
 * @param {Function} mainClass a reference to class in the module.  This
149
 *                             class will be tagged with the version info
150
 *                             so that it will be possible to identify the
151
 *                             version that is in use when multiple versions
152
 *                             have loaded
153
 * @param {Object}   data      metadata object for the module.  Currently it
154
 *                             is expected to contain a "version" property
155
 *                             and a "build" property at minimum.
156
 */
157
YAHOO.register = function(name, mainClass, data) {
158
    var mods = YAHOO.env.modules, m, v, b, ls, i;
159

    
160
    if (!mods[name]) {
161
        mods[name] = { 
162
            versions:[], 
163
            builds:[] 
164
        };
165
    }
166

    
167
    m  = mods[name];
168
    v  = data.version;
169
    b  = data.build;
170
    ls = YAHOO.env.listeners;
171

    
172
    m.name = name;
173
    m.version = v;
174
    m.build = b;
175
    m.versions.push(v);
176
    m.builds.push(b);
177
    m.mainClass = mainClass;
178

    
179
    // fire the module load listeners
180
    for (i=0;i<ls.length;i=i+1) {
181
        ls[i](m);
182
    }
183
    // label the main class
184
    if (mainClass) {
185
        mainClass.VERSION = v;
186
        mainClass.BUILD = b;
187
    } else {
188
        YAHOO.log("mainClass is undefined for module " + name, "warn");
189
    }
190
};
191

    
192
/**
193
 * YAHOO.env is used to keep track of what is known about the YUI library and
194
 * the browsing environment
195
 * @class YAHOO.env
196
 * @static
197
 */
198
YAHOO.env = YAHOO.env || {
199

    
200
    /**
201
     * Keeps the version info for all YUI modules that have reported themselves
202
    * @property modules
203
    * @type Object[]
204
     */
205
    modules: [],
206
    
207
    /**
208
     * List of functions that should be executed every time a YUI module
209
     * reports itself.
210
    * @property listeners
211
    * @type Function[]
212
     */
213
    listeners: []
214
};
215

    
216
/**
217
 * Returns the version data for the specified module:
218
 *      <dl>
219
 *      <dt>name:</dt>      <dd>The name of the module</dd>
220
 *      <dt>version:</dt>   <dd>The version in use</dd>
221
 *      <dt>build:</dt>     <dd>The build number in use</dd>
222
 *      <dt>versions:</dt>  <dd>All versions that were registered</dd>
223
 *      <dt>builds:</dt>    <dd>All builds that were registered.</dd>
224
 *      <dt>mainClass:</dt> <dd>An object that was was stamped with the
225
 *                 current version and build. If 
226
 *                 mainClass.VERSION != version or mainClass.BUILD != build,
227
 *                 multiple versions of pieces of the library have been
228
 *                 loaded, potentially causing issues.</dd>
229
 *       </dl>
230
 *
231
 * @method getVersion
232
 * @static
233
 * @param {String}  name the name of the module (event, slider, etc)
234
 * @return {Object} The version info
235
 */
236
YAHOO.env.getVersion = function(name) {
237
    return YAHOO.env.modules[name] || null;
238
};
239

    
240
/**
241
 * Do not fork for a browser if it can be avoided.  Use feature detection when
242
 * you can.  Use the user agent as a last resort.  YAHOO.env.ua stores a version
243
 * number for the browser engine, 0 otherwise.  This value may or may not map
244
 * to the version number of the browser using the engine.  The value is 
245
 * presented as a float so that it can easily be used for boolean evaluation 
246
 * as well as for looking for a particular range of versions.  Because of this, 
247
 * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 
248
 * reports 1.8).
249
 * @class YAHOO.env.ua
250
 * @static
251
 */
252
YAHOO.env.ua = function() {
253

    
254
        var numberfy = function(s) {
255
            var c = 0;
256
            return parseFloat(s.replace(/\./g, function() {
257
                return (c++ == 1) ? '' : '.';
258
            }));
259
        },
260

    
261
        nav = navigator,
262

    
263
        o = {
264

    
265
        /**
266
         * Internet Explorer version number or 0.  Example: 6
267
        * @property ie
268
        * @type float
269
         */
270
        ie: 0,
271

    
272
        /**
273
         * Opera version number or 0.  Example: 9.2
274
        * @property opera
275
        * @type float
276
         */
277
        opera: 0,
278

    
279
        /**
280
         * Gecko engine revision number.  Will evaluate to 1 if Gecko 
281
         * is detected but the revision could not be found. Other browsers
282
         * will be 0.  Example: 1.8
283
         * <pre>
284
         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
285
         * Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8
286
         * Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8
287
         * Firefox 3 alpha: 1.9a4   <-- Reports 1.9
288
         * </pre>
289
        * @property gecko
290
        * @type float
291
         */
292
        gecko: 0,
293

    
294
        /**
295
         * AppleWebKit version.  KHTML browsers that are not WebKit browsers 
296
         * will evaluate to 1, other browsers 0.  Example: 418.9.1
297
         * <pre>
298
         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the 
299
         *                                   latest available for Mac OSX 10.3.
300
         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
301
         * Safari 2.0.4:         418     <-- preventDefault fixed
302
         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
303
         *                                   different versions of webkit
304
         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
305
         *                                   updated, but not updated
306
         *                                   to the latest patch.
307
         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native SVG
308
         *                                   and many major issues fixed).  
309
         * 3.x yahoo.com, flickr:422     <-- Safari 3.x hacks the user agent
310
         *                                   string when hitting yahoo.com and 
311
         *                                   flickr.com.
312
         * Safari 3.0.4 (523.12):523.12  <-- First Tiger release - automatic update
313
         *                                   from 2.x via the 10.4.11 OS patch
314
         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
315
         *                                   yahoo.com user agent hack removed.
316
         *                                   
317
         * </pre>
318
         * http://developer.apple.com/internet/safari/uamatrix.html
319
        * @property webkit
320
        * @type float
321
         */
322
        webkit: 0,
323

    
324
        /**
325
         * The mobile property will be set to a string containing any relevant
326
         * user agent information when a modern mobile browser is detected.
327
         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
328
         * devices with the WebKit-based browser, and Opera Mini.  
329
        * @property mobile 
330
        * @type string
331
         */
332
        mobile: null,
333

    
334
        /**
335
         * Adobe AIR version number or 0.  Only populated if webkit is detected.
336
         * Example: 1.0
337
        * @property air
338
        * @type float
339
         */
340
        air: 0,
341

    
342
        /**
343
         * Google Caja version number or 0.
344
        * @property caja
345
        * @type float
346
         */
347
        caja: nav.cajaVersion,
348

    
349
        /**
350
         * Set to true if the page appears to be in SSL
351
        * @property secure
352
        * @type boolean
353
        * @static
354
         */
355
        secure: false,
356

    
357
        /**
358
         * The operating system.  Currently only detecting windows or macintosh
359
        * @property os
360
        * @type string
361
        * @static
362
         */
363
        os: null
364

    
365
    },
366

    
367
    ua = navigator && navigator.userAgent, 
368
    
369
    loc = window && window.location,
370

    
371
    href = loc && loc.href,
372
    
373
    m;
374

    
375
    o.secure = href && (href.toLowerCase().indexOf("https") === 0);
376

    
377
    if (ua) {
378

    
379
        if ((/windows|win32/i).test(ua)) {
380
            o.os = 'windows';
381
        } else if ((/macintosh/i).test(ua)) {
382
            o.os = 'macintosh';
383
        }
384
    
385
        // Modern KHTML browsers should qualify as Safari X-Grade
386
        if ((/KHTML/).test(ua)) {
387
            o.webkit=1;
388
        }
389

    
390
        // Modern WebKit browsers are at least X-Grade
391
        m=ua.match(/AppleWebKit\/([^\s]*)/);
392
        if (m&&m[1]) {
393
            o.webkit=numberfy(m[1]);
394

    
395
            // Mobile browser check
396
            if (/ Mobile\//.test(ua)) {
397
                o.mobile = "Apple"; // iPhone or iPod Touch
398
            } else {
399
                m=ua.match(/NokiaN[^\/]*/);
400
                if (m) {
401
                    o.mobile = m[0]; // Nokia N-series, ex: NokiaN95
402
                }
403
            }
404

    
405
            m=ua.match(/AdobeAIR\/([^\s]*)/);
406
            if (m) {
407
                o.air = m[0]; // Adobe AIR 1.0 or better
408
            }
409

    
410
        }
411

    
412
        if (!o.webkit) { // not webkit
413
            // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
414
            m=ua.match(/Opera[\s\/]([^\s]*)/);
415
            if (m&&m[1]) {
416
                o.opera=numberfy(m[1]);
417
                m=ua.match(/Opera Mini[^;]*/);
418
                if (m) {
419
                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
420
                }
421
            } else { // not opera or webkit
422
                m=ua.match(/MSIE\s([^;]*)/);
423
                if (m&&m[1]) {
424
                    o.ie=numberfy(m[1]);
425
                } else { // not opera, webkit, or ie
426
                    m=ua.match(/Gecko\/([^\s]*)/);
427
                    if (m) {
428
                        o.gecko=1; // Gecko detected, look for revision
429
                        m=ua.match(/rv:([^\s\)]*)/);
430
                        if (m&&m[1]) {
431
                            o.gecko=numberfy(m[1]);
432
                        }
433
                    }
434
                }
435
            }
436
        }
437
    }
438

    
439
    return o;
440
}();
441

    
442
/*
443
 * Initializes the global by creating the default namespaces and applying
444
 * any new configuration information that is detected.  This is the setup
445
 * for env.
446
 * @method init
447
 * @static
448
 * @private
449
 */
450
(function() {
451
    YAHOO.namespace("util", "widget", "example");
452
    /*global YAHOO_config*/
453
    if ("undefined" !== typeof YAHOO_config) {
454
        var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i;
455
        if (l) {
456
            // if YAHOO is loaded multiple times we need to check to see if
457
            // this is a new config object.  If it is, add the new component
458
            // load listener to the stack
459
            for (i=0; i<ls.length; i++) {
460
                if (ls[i] == l) {
461
                    unique = false;
462
                    break;
463
                }
464
            }
465

    
466
            if (unique) {
467
                ls.push(l);
468
            }
469
        }
470
    }
471
})();
472
/**
473
 * Provides the language utilites and extensions used by the library
474
 * @class YAHOO.lang
475
 */
476
YAHOO.lang = YAHOO.lang || {};
477

    
478
(function() {
479

    
480

    
481
var L = YAHOO.lang,
482

    
483
    OP = Object.prototype,
484
    ARRAY_TOSTRING = '[object Array]',
485
    FUNCTION_TOSTRING = '[object Function]',
486
    OBJECT_TOSTRING = '[object Object]',
487
    NOTHING = [],
488

    
489
    // ADD = ["toString", "valueOf", "hasOwnProperty"],
490
    ADD = ["toString", "valueOf"],
491

    
492
    OB = {
493

    
494
    /**
495
     * Determines wheather or not the provided object is an array.
496
    * @method isArray
497
    * @param {any} o The object being testing
498
    * @return {boolean} the result
499
     */
500
    isArray: function(o) { 
501
        return OP.toString.apply(o) === ARRAY_TOSTRING;
502
    },
503

    
504
    /**
505
     * Determines whether or not the provided object is a boolean
506
    * @method isBoolean
507
    * @param {any} o The object being testing
508
    * @return {boolean} the result
509
     */
510
    isBoolean: function(o) {
511
        return typeof o === 'boolean';
512
    },
513
    
514
    /**
515
     * Determines whether or not the provided object is a function.
516
     * Note: Internet Explorer thinks certain functions are objects:
517
     *
518
     * var obj = document.createElement("object");
519
     * YAHOO.lang.isFunction(obj.getAttribute) // reports false in IE
520
     *
521
     * var input = document.createElement("input"); // append to body
522
     * YAHOO.lang.isFunction(input.focus) // reports false in IE
523
     *
524
     * You will have to implement additional tests if these functions
525
     * matter to you.
526
     *
527
    * @method isFunction
528
    * @param {any} o The object being testing
529
    * @return {boolean} the result
530
     */
531
    isFunction: function(o) {
532
        return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING;
533
    },
534
        
535
    /**
536
     * Determines whether or not the provided object is null
537
    * @method isNull
538
    * @param {any} o The object being testing
539
    * @return {boolean} the result
540
     */
541
    isNull: function(o) {
542
        return o === null;
543
    },
544
        
545
    /**
546
     * Determines whether or not the provided object is a legal number
547
    * @method isNumber
548
    * @param {any} o The object being testing
549
    * @return {boolean} the result
550
     */
551
    isNumber: function(o) {
552
        return typeof o === 'number' && isFinite(o);
553
    },
554
      
555
    /**
556
     * Determines whether or not the provided object is of type object
557
     * or function
558
    * @method isObject
559
    * @param {any} o The object being testing
560
    * @return {boolean} the result
561
     */  
562
    isObject: function(o) {
563
return (o && (typeof o === 'object' || L.isFunction(o))) || false;
564
    },
565
        
566
    /**
567
     * Determines whether or not the provided object is a string
568
    * @method isString
569
    * @param {any} o The object being testing
570
    * @return {boolean} the result
571
     */
572
    isString: function(o) {
573
        return typeof o === 'string';
574
    },
575
        
576
    /**
577
     * Determines whether or not the provided object is undefined
578
    * @method isUndefined
579
    * @param {any} o The object being testing
580
    * @return {boolean} the result
581
     */
582
    isUndefined: function(o) {
583
        return typeof o === 'undefined';
584
    },
585
    
586
 
587
    /**
588
     * IE will not enumerate native functions in a derived object even if the
589
     * function was overridden.  This is a workaround for specific functions 
590
     * we care about on the Object prototype. 
591
    * @property _IEEnumFix
592
    * @param {Function} r  the object to receive the augmentation
593
    * @param {Function} s  the object that supplies the properties to augment
594
    * @static
595
    * @private
596
     */
597
    _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) {
598
            var i, fname, f;
599
            for (i=0;i<ADD.length;i=i+1) {
600

    
601
                fname = ADD[i];
602
                f = s[fname];
603

    
604
                if (L.isFunction(f) && f!=OP[fname]) {
605
                    r[fname]=f;
606
                }
607
            }
608
    } : function(){},
609
       
610
    /**
611
     * Utility to set up the prototype, constructor and superclass properties to
612
     * support an inheritance strategy that can chain constructors and methods.
613
     * Static members will not be inherited.
614
     *
615
    * @method extend
616
    * @static
617
    * @param {Function} subc   the object to modify
618
    * @param {Function} superc the object to inherit
619
    * @param {Object} overrides  additional properties/methods to add to the
620
     *                              subclass prototype.  These will override the
621
     *                              matching items obtained from the superclass 
622
     *                              if present.
623
     */
624
    extend: function(subc, superc, overrides) {
625
        if (!superc||!subc) {
626
            throw new Error("extend failed, please check that " +
627
                            "all dependencies are included.");
628
        }
629
        var F = function() {}, i;
630
        F.prototype=superc.prototype;
631
        subc.prototype=new F();
632
        subc.prototype.constructor=subc;
633
        subc.superclass=superc.prototype;
634
        if (superc.prototype.constructor == OP.constructor) {
635
            superc.prototype.constructor=superc;
636
        }
637
    
638
        if (overrides) {
639
            for (i in overrides) {
640
                if (L.hasOwnProperty(overrides, i)) {
641
                    subc.prototype[i]=overrides[i];
642
                }
643
            }
644

    
645
            L._IEEnumFix(subc.prototype, overrides);
646
        }
647
    },
648
   
649
    /**
650
     * Applies all properties in the supplier to the receiver if the
651
     * receiver does not have these properties yet.  Optionally, one or 
652
     * more methods/properties can be specified (as additional 
653
     * parameters).  This option will overwrite the property if receiver 
654
     * has it already.  If true is passed as the third parameter, all 
655
     * properties will be applied and _will_ overwrite properties in 
656
     * the receiver.
657
     *
658
    * @method augmentObject
659
    * @static
660
    * @since 2.3.0
661
    * @param {Function} r  the object to receive the augmentation
662
    * @param {Function} s  the object that supplies the properties to augment
663
    * @param {String*|boolean}  arguments zero or more properties methods 
664
     *        to augment the receiver with.  If none specified, everything
665
     *        in the supplier will be used unless it would
666
     *        overwrite an existing property in the receiver. If true
667
     *        is specified as the third parameter, all properties will
668
     *        be applied and will overwrite an existing property in
669
     *        the receiver
670
     */
671
    augmentObject: function(r, s) {
672
        if (!s||!r) {
673
            throw new Error("Absorb failed, verify dependencies.");
674
        }
675
        var a=arguments, i, p, overrideList=a[2];
676
        if (overrideList && overrideList!==true) { // only absorb the specified properties
677
            for (i=2; i<a.length; i=i+1) {
678
                r[a[i]] = s[a[i]];
679
            }
680
        } else { // take everything, overwriting only if the third parameter is true
681
            for (p in s) { 
682
                if (overrideList || !(p in r)) {
683
                    r[p] = s[p];
684
                }
685
            }
686
            
687
            L._IEEnumFix(r, s);
688
        }
689
    },
690
 
691
    /**
692
     * Same as YAHOO.lang.augmentObject, except it only applies prototype properties
693
    * @see YAHOO.lang.augmentObject
694
    * @method augmentProto
695
    * @static
696
    * @param {Function} r  the object to receive the augmentation
697
    * @param {Function} s  the object that supplies the properties to augment
698
    * @param {String*|boolean}  arguments zero or more properties methods 
699
     *        to augment the receiver with.  If none specified, everything 
700
     *        in the supplier will be used unless it would overwrite an existing 
701
     *        property in the receiver.  if true is specified as the third 
702
     *        parameter, all properties will be applied and will overwrite an 
703
     *        existing property in the receiver
704
     */
705
    augmentProto: function(r, s) {
706
        if (!s||!r) {
707
            throw new Error("Augment failed, verify dependencies.");
708
        }
709
        //var a=[].concat(arguments);
710
        var a=[r.prototype,s.prototype], i;
711
        for (i=2;i<arguments.length;i=i+1) {
712
            a.push(arguments[i]);
713
        }
714
        L.augmentObject.apply(this, a);
715
    },
716

    
717
      
718
    /**
719
     * Returns a simple string representation of the object or array.
720
     * Other types of objects will be returned unprocessed.  Arrays
721
     * are expected to be indexed.  Use object notation for
722
     * associative arrays.
723
    * @method dump
724
    * @since 2.3.0
725
    * @param o {Object} The object to dump
726
    * @param d {int} How deep to recurse child objects, default 3
727
    * @return {String} the dump result
728
     */
729
    dump: function(o, d) {
730
        var i,len,s=[],OBJ="{...}",FUN="f(){...}",
731
            COMMA=', ', ARROW=' => ';
732

    
733
        // Cast non-objects to string
734
        // Skip dates because the std toString is what we want
735
        // Skip HTMLElement-like objects because trying to dump 
736
        // an element will cause an unhandled exception in FF 2.x
737
        if (!L.isObject(o)) {
738
            return o + "";
739
        } else if (o instanceof Date || ("nodeType" in o && "tagName" in o)) {
740
            return o;
741
        } else if  (L.isFunction(o)) {
742
            return FUN;
743
        }
744

    
745
        // dig into child objects the depth specifed. Default 3
746
        d = (L.isNumber(d)) ? d : 3;
747

    
748
        // arrays [1, 2, 3]
749
        if (L.isArray(o)) {
750
            s.push("[");
751
            for (i=0,len=o.length;i<len;i=i+1) {
752
                if (L.isObject(o[i])) {
753
                    s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
754
                } else {
755
                    s.push(o[i]);
756
                }
757
                s.push(COMMA);
758
            }
759
            if (s.length > 1) {
760
                s.pop();
761
            }
762
            s.push("]");
763
        // objects {k1 => v1, k2 => v2}
764
        } else {
765
            s.push("{");
766
            for (i in o) {
767
                if (L.hasOwnProperty(o, i)) {
768
                    s.push(i + ARROW);
769
                    if (L.isObject(o[i])) {
770
                        s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
771
                    } else {
772
                        s.push(o[i]);
773
                    }
774
                    s.push(COMMA);
775
                }
776
            }
777
            if (s.length > 1) {
778
                s.pop();
779
            }
780
            s.push("}");
781
        }
782

    
783
        return s.join("");
784
    },
785

    
786
    /**
787
     * Does variable substitution on a string. It scans through the string 
788
     * looking for expressions enclosed in { } braces. If an expression 
789
     * is found, it is used a key on the object.  If there is a space in
790
     * the key, the first word is used for the key and the rest is provided
791
     * to an optional function to be used to programatically determine the
792
     * value (the extra information might be used for this decision). If 
793
     * the value for the key in the object, or what is returned from the
794
     * function has a string value, number value, or object value, it is 
795
     * substituted for the bracket expression and it repeats.  If this
796
     * value is an object, it uses the Object's toString() if this has
797
     * been overridden, otherwise it does a shallow dump of the key/value
798
     * pairs.
799
    * @method substitute
800
    * @since 2.3.0
801
    * @param s {String} The string that will be modified.
802
    * @param o {Object} An object containing the replacement values
803
    * @param f {Function} An optional function that can be used to
804
     *                     process each match.  It receives the key,
805
     *                     value, and any extra metadata included with
806
     *                     the key inside of the braces.
807
    * @return {String} the substituted string
808
     */
809
    substitute: function (s, o, f) {
810
        var i, j, k, key, v, meta, saved=[], token, 
811
            DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}',
812
            dump, objstr;
813

    
814

    
815
        for (;;) {
816
            i = s.lastIndexOf(LBRACE);
817
            if (i < 0) {
818
                break;
819
            }
820
            j = s.indexOf(RBRACE, i);
821
            if (i + 1 >= j) {
822
                break;
823
            }
824

    
825
            //Extract key and meta info 
826
            token = s.substring(i + 1, j);
827
            key = token;
828
            meta = null;
829
            k = key.indexOf(SPACE);
830
            if (k > -1) {
831
                meta = key.substring(k + 1);
832
                key = key.substring(0, k);
833
            }
834

    
835
            // lookup the value
836
            v = o[key];
837

    
838
            // if a substitution function was provided, execute it
839
            if (f) {
840
                v = f(key, v, meta);
841
            }
842

    
843
            if (L.isObject(v)) {
844
                if (L.isArray(v)) {
845
                    v = L.dump(v, parseInt(meta, 10));
846
                } else {
847
                    meta = meta || "";
848

    
849
                    // look for the keyword 'dump', if found force obj dump
850
                    dump = meta.indexOf(DUMP);
851
                    if (dump > -1) {
852
                        meta = meta.substring(4);
853
                    }
854

    
855
                    objstr = v.toString();
856

    
857
                    // use the toString if it is not the Object toString 
858
                    // and the 'dump' meta info was not found
859
                    if (objstr === OBJECT_TOSTRING || dump > -1) {
860
                        v = L.dump(v, parseInt(meta, 10));
861
                    } else {
862
                        v = objstr;
863
                    }
864
                }
865
            } else if (!L.isString(v) && !L.isNumber(v)) {
866
                // This {block} has no replace string. Save it for later.
867
                v = "~-" + saved.length + "-~";
868
                saved[saved.length] = token;
869

    
870
                // break;
871
            }
872

    
873
            s = s.substring(0, i) + v + s.substring(j + 1);
874

    
875

    
876
        }
877

    
878
        // restore saved {block}s
879
        for (i=saved.length-1; i>=0; i=i-1) {
880
            s = s.replace(new RegExp("~-" + i + "-~"), "{"  + saved[i] + "}", "g");
881
        }
882

    
883
        return s;
884
    },
885

    
886

    
887
    /**
888
     * Returns a string without any leading or trailing whitespace.  If 
889
     * the input is not a string, the input will be returned untouched.
890
    * @method trim
891
    * @since 2.3.0
892
    * @param s {string} the string to trim
893
    * @return {string} the trimmed string
894
     */
895
    trim: function(s){
896
        try {
897
            return s.replace(/^\s+|\s+$/g, "");
898
        } catch(e) {
899
            return s;
900
        }
901
    },
902

    
903
    /**
904
     * Returns a new object containing all of the properties of
905
     * all the supplied objects.  The properties from later objects
906
     * will overwrite those in earlier objects.
907
    * @method merge
908
    * @since 2.3.0
909
    * @param arguments {Object*} the objects to merge
910
    * @return the new merged object
911
     */
912
    merge: function() {
913
        var o={}, a=arguments, l=a.length, i;
914
        for (i=0; i<l; i=i+1) {
915
            L.augmentObject(o, a[i], true);
916
        }
917
        return o;
918
    },
919

    
920
    /**
921
     * Executes the supplied function in the context of the supplied 
922
     * object 'when' milliseconds later.  Executes the function a 
923
     * single time unless periodic is set to true.
924
    * @method later
925
    * @since 2.4.0
926
    * @param when {int} the number of milliseconds to wait until the fn 
927
     * is executed
928
    * @param o the context object
929
    * @param fn {Function|String} the function to execute or the name of 
930
     * the method in the 'o' object to execute
931
    * @param data [Array] data that is provided to the function.  This accepts
932
     * either a single item or an array.  If an array is provided, the
933
     * function is executed with one parameter for each array item.  If
934
     * you need to pass a single array parameter, it needs to be wrapped in
935
     * an array [myarray]
936
    * @param periodic {boolean} if true, executes continuously at supplied 
937
     * interval until canceled
938
    * @return a timer object. Call the cancel() method on this object to 
939
     * stop the timer.
940
     */
941
    later: function(when, o, fn, data, periodic) {
942
        when = when || 0; 
943
        o = o || {};
944
        var m=fn, d=data, f, r;
945

    
946
        if (L.isString(fn)) {
947
            m = o[fn];
948
        }
949

    
950
        if (!m) {
951
            throw new TypeError("method undefined");
952
        }
953

    
954
        if (d && !L.isArray(d)) {
955
            d = [data];
956
        }
957

    
958
        f = function() {
959
            m.apply(o, d || NOTHING);
960
        };
961

    
962
        r = (periodic) ? setInterval(f, when) : setTimeout(f, when);
963

    
964
        return {
965
            interval: periodic,
966
            cancel: function() {
967
                if (this.interval) {
968
                    clearInterval(r);
969
                } else {
970
                    clearTimeout(r);
971
                }
972
            }
973
        };
974
    },
975
    
976
    /**
977
     * A convenience method for detecting a legitimate non-null value.
978
     * Returns false for null/undefined/NaN, true for other values, 
979
     * including 0/false/''
980
    * @method isValue
981
    * @since 2.3.0
982
    * @param o {any} the item to test
983
    * @return {boolean} true if it is not null/undefined/NaN || false
984
     */
985
    isValue: function(o) {
986
        // return (o || o === false || o === 0 || o === ''); // Infinity fails
987
return (L.isObject(o) || L.isString(o) || L.isNumber(o) || L.isBoolean(o));
988
    }
989

    
990
};
991

    
992
/**
993
 * Determines whether or not the property was added
994
 * to the object instance.  Returns false if the property is not present
995
 * in the object, or was inherited from the prototype.
996
 * This abstraction is provided to enable hasOwnProperty for Safari 1.3.x.
997
 * There is a discrepancy between YAHOO.lang.hasOwnProperty and
998
 * Object.prototype.hasOwnProperty when the property is a primitive added to
999
 * both the instance AND prototype with the same value:
1000
 * <pre>
1001
 * var A = function() {};
1002
 * A.prototype.foo = 'foo';
1003
 * var a = new A();
1004
 * a.foo = 'foo';
1005
 * alert(a.hasOwnProperty('foo')); // true
1006
 * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback
1007
 * </pre>
1008
 * @method hasOwnProperty
1009
 * @param {any} o The object being testing
1010
 * @param prop {string} the name of the property to test
1011
 * @return {boolean} the result
1012
 */
1013
L.hasOwnProperty = (OP.hasOwnProperty) ?
1014
    function(o, prop) {
1015
        return o && o.hasOwnProperty(prop);
1016
    } : function(o, prop) {
1017
        return !L.isUndefined(o[prop]) && 
1018
                o.constructor.prototype[prop] !== o[prop];
1019
    };
1020

    
1021
// new lang wins
1022
OB.augmentObject(L, OB, true);
1023

    
1024
/*
1025
 * An alias for <a href="YAHOO.lang.html">YAHOO.lang</a>
1026
 * @class YAHOO.util.Lang
1027
 */
1028
YAHOO.util.Lang = L;
1029
 
1030
/**
1031
 * Same as YAHOO.lang.augmentObject, except it only applies prototype 
1032
 * properties.  This is an alias for augmentProto.
1033
 * @see YAHOO.lang.augmentObject
1034
 * @method augment
1035
 * @static
1036
 * @param {Function} r  the object to receive the augmentation
1037
 * @param {Function} s  the object that supplies the properties to augment
1038
 * @param {String*|boolean}  arguments zero or more properties methods to 
1039
 *        augment the receiver with.  If none specified, everything
1040
 *        in the supplier will be used unless it would
1041
 *        overwrite an existing property in the receiver.  if true
1042
 *        is specified as the third parameter, all properties will
1043
 *        be applied and will overwrite an existing property in
1044
 *        the receiver
1045
 */
1046
L.augment = L.augmentProto;
1047

    
1048
/**
1049
 * An alias for <a href="YAHOO.lang.html#augment">YAHOO.lang.augment</a>
1050
 * @for YAHOO
1051
 * @method augment
1052
 * @static
1053
 * @param {Function} r  the object to receive the augmentation
1054
 * @param {Function} s  the object that supplies the properties to augment
1055
 * @param {String*}  arguments zero or more properties methods to 
1056
 *        augment the receiver with.  If none specified, everything
1057
 *        in the supplier will be used unless it would
1058
 *        overwrite an existing property in the receiver
1059
 */
1060
YAHOO.augment = L.augmentProto;
1061
       
1062
/**
1063
 * An alias for <a href="YAHOO.lang.html#extend">YAHOO.lang.extend</a>
1064
 * @method extend
1065
 * @static
1066
 * @param {Function} subc   the object to modify
1067
 * @param {Function} superc the object to inherit
1068
 * @param {Object} overrides  additional properties/methods to add to the
1069
 *        subclass prototype.  These will override the
1070
 *        matching items obtained from the superclass if present.
1071
 */
1072
YAHOO.extend = L.extend;
1073

    
1074
})();
1075
YAHOO.register("yahoo", YAHOO, {version: "2.8.0r4", build: "2449"});
(5-5/5)