~bac/juju-gui/trunkcopy

« back to all changes in this revision

Viewing changes to lib/yui/build/base-core/base-core-debug.js

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
YUI 3.5.1 (build 22)
3
 
Copyright 2012 Yahoo! Inc. All rights reserved.
4
 
Licensed under the BSD License.
5
 
http://yuilibrary.com/license/
6
 
*/
7
 
YUI.add('base-core', function(Y) {
8
 
 
9
 
    /**
10
 
     * The base module provides the Base class, which objects requiring attribute and custom event support can extend. 
11
 
     * The module also provides two ways to reuse code - It augments Base with the Plugin.Host interface which provides 
12
 
     * plugin support and also provides the BaseCore.build method which provides a way to build custom classes using extensions.
13
 
     *
14
 
     * @module base
15
 
     */
16
 
 
17
 
    /**
18
 
     * <p>The base-core module provides the BaseCore class, the lightest version of Base, 
19
 
     * which provides Base's basic lifecycle management and ATTRS construction support, 
20
 
     * but doesn't fire init/destroy or attribute change events.</p> 
21
 
     * 
22
 
     * <p>It mixes in AttributeCore, which is the lightest version of Attribute</p>
23
 
     *
24
 
     * @module base
25
 
     * @submodule base-core
26
 
     */
27
 
    var O = Y.Object,
28
 
        L = Y.Lang,
29
 
        DOT = ".",
30
 
        INITIALIZED = "initialized",
31
 
        DESTROYED = "destroyed",
32
 
        INITIALIZER = "initializer",
33
 
        OBJECT_CONSTRUCTOR = Object.prototype.constructor,
34
 
        DEEP = "deep",
35
 
        SHALLOW = "shallow",
36
 
        DESTRUCTOR = "destructor",
37
 
 
38
 
        AttributeCore = Y.AttributeCore,
39
 
 
40
 
        _wlmix = function(r, s, wlhash) {
41
 
            var p;
42
 
            for (p in s) {
43
 
                if(wlhash[p]) { 
44
 
                    r[p] = s[p];
45
 
                }
46
 
            }
47
 
            return r;
48
 
        };
49
 
 
50
 
    /**
51
 
     * The BaseCore class, is the lightest version of Base, and provides Base's 
52
 
     * basic lifecycle management and ATTRS construction support, but doesn't 
53
 
     * fire init/destroy or attribute change events.
54
 
     *
55
 
     * BaseCore also handles the chaining of initializer and destructor methods across 
56
 
     * the hierarchy as part of object construction and destruction. Additionally, attributes 
57
 
     * configured through the static <a href="#property_BaseCore.ATTRS">ATTRS</a> 
58
 
     * property for each class in the hierarchy will be initialized by BaseCore.
59
 
     *
60
 
     * Classes which require attribute support, but don't intend to use/expose attribute 
61
 
     * change events can extend BaseCore instead of Base for optimal kweight and 
62
 
     * runtime performance.
63
 
     * 
64
 
     * @class BaseCore
65
 
     * @constructor
66
 
     * @uses AttributeCore
67
 
     * @param {Object} cfg Object with configuration property name/value pairs. 
68
 
     * The object can be used to provide initial values for the objects published 
69
 
     * attributes.
70
 
     */
71
 
    function BaseCore(cfg) {
72
 
        if (!this._BaseInvoked) {
73
 
            this._BaseInvoked = true;
74
 
 
75
 
            Y.log('constructor called', 'life', 'base');
76
 
            this._initBase(cfg);
77
 
        }
78
 
        else { Y.log('Based constructor called more than once. Ignoring duplicate calls', 'life', 'base'); }
79
 
    }
80
 
 
81
 
    /**
82
 
     * The list of properties which can be configured for each attribute 
83
 
     * (e.g. setter, getter, writeOnce, readOnly etc.)
84
 
     *
85
 
     * @property _ATTR_CFG
86
 
     * @type Array
87
 
     * @static
88
 
     * @private
89
 
     */
90
 
    BaseCore._ATTR_CFG = AttributeCore._ATTR_CFG.concat("cloneDefaultValue");
91
 
    BaseCore._ATTR_CFG_HASH = Y.Array.hash(BaseCore._ATTR_CFG);
92
 
 
93
 
    /**
94
 
     * The array of non-attribute configuration properties supported by this class. 
95
 
     * 
96
 
     * For example `BaseCore` defines a "plugins" configuration property which 
97
 
     * should not be set up as an attribute. This property is primarily required so 
98
 
     * that when <a href="#property__allowAdHocAttrs">`_allowAdHocAttrs`</a> is enabled by a class, 
99
 
     * non-attribute configuration properties don't get added as ad-hoc attributes.  
100
 
     *
101
 
     * @property _NON_ATTRS_CFG
102
 
     * @type Array
103
 
     * @static
104
 
     * @private
105
 
     */
106
 
    BaseCore._NON_ATTRS_CFG = ["plugins"];
107
 
 
108
 
    /**
109
 
     * This property controls whether or not instances of this class should
110
 
     * allow users to add ad-hoc attributes through the constructor configuration 
111
 
     * hash.
112
 
     *
113
 
     * AdHoc attributes are attributes which are not defined by the class, and are 
114
 
     * not handled by the MyClass._NON_ATTRS_CFG  
115
 
     * 
116
 
     * @property _allowAdHocAttrs
117
 
     * @type boolean
118
 
     * @default undefined (false)
119
 
     * @protected
120
 
     */
121
 
 
122
 
    /**
123
 
     * The string to be used to identify instances of this class.
124
 
     * 
125
 
     * Classes extending BaseCore, should define their own
126
 
     * static NAME property, which should be camelCase by
127
 
     * convention (e.g. MyClass.NAME = "myClass";).
128
 
     *
129
 
     * @property NAME
130
 
     * @type String
131
 
     * @static
132
 
     */
133
 
    BaseCore.NAME = "baseCore";
134
 
 
135
 
    /**
136
 
     * The default set of attributes which will be available for instances of this class, and 
137
 
     * their configuration. In addition to the configuration properties listed by 
138
 
     * AttributeCore's <a href="AttributeCore.html#method_addAttr">addAttr</a> method, 
139
 
     * the attribute can also be configured with a "cloneDefaultValue" property, which 
140
 
     * defines how the statically defined value field should be protected 
141
 
     * ("shallow", "deep" and false are supported values). 
142
 
     *
143
 
     * By default if the value is an object literal or an array it will be "shallow" 
144
 
     * cloned, to protect the default value.
145
 
     *
146
 
     * @property ATTRS
147
 
     * @type Object
148
 
     * @static
149
 
     */
150
 
    BaseCore.ATTRS = {
151
 
        /**
152
 
         * Flag indicating whether or not this object
153
 
         * has been through the init lifecycle phase.
154
 
         *
155
 
         * @attribute initialized
156
 
         * @readonly
157
 
         * @default false
158
 
         * @type boolean
159
 
         */
160
 
        initialized: {
161
 
            readOnly:true,
162
 
            value:false
163
 
        },
164
 
 
165
 
        /**
166
 
         * Flag indicating whether or not this object
167
 
         * has been through the destroy lifecycle phase.
168
 
         *
169
 
         * @attribute destroyed
170
 
         * @readonly
171
 
         * @default false
172
 
         * @type boolean
173
 
         */
174
 
        destroyed: {
175
 
            readOnly:true,
176
 
            value:false
177
 
        }
178
 
    };
179
 
 
180
 
    BaseCore.prototype = {
181
 
 
182
 
        /**
183
 
         * Internal construction logic for BaseCore.
184
 
         *
185
 
         * @method _initBase
186
 
         * @param {Object} config The constructor configuration object
187
 
         * @private
188
 
         */
189
 
        _initBase : function(config) {
190
 
 
191
 
            Y.stamp(this);
192
 
 
193
 
            this._initAttribute(config);
194
 
 
195
 
            // If Plugin.Host has been augmented [ through base-pluginhost ], setup it's
196
 
            // initial state, but don't initialize Plugins yet. That's done after initialization.
197
 
            var PluginHost = Y.Plugin && Y.Plugin.Host;
198
 
            if (this._initPlugins && PluginHost) {
199
 
                PluginHost.call(this);
200
 
            }
201
 
 
202
 
            if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
203
 
 
204
 
            /**
205
 
             * The string used to identify the class of this object.
206
 
             *
207
 
             * @deprecated Use this.constructor.NAME
208
 
             * @property name
209
 
             * @type String
210
 
             */
211
 
            this.name = this.constructor.NAME;
212
 
    
213
 
            this.init.apply(this, arguments);
214
 
        },
215
 
 
216
 
        /**
217
 
         * Initializes AttributeCore 
218
 
         * 
219
 
         * @method _initAttribute
220
 
         * @private
221
 
         */
222
 
        _initAttribute: function() {
223
 
            AttributeCore.apply(this);
224
 
        },
225
 
 
226
 
        /**
227
 
         * Init lifecycle method, invoked during construction. Sets up attributes 
228
 
         * and invokes initializers for the class hierarchy.
229
 
         *
230
 
         * @method init
231
 
         * @chainable
232
 
         * @param {Object} cfg Object with configuration property name/value pairs
233
 
         * @return {BaseCore} A reference to this object
234
 
         */
235
 
        init: function(cfg) {
236
 
            Y.log('init called', 'life', 'base');
237
 
 
238
 
            this._baseInit(cfg);
239
 
 
240
 
            return this;
241
 
        },
242
 
 
243
 
        /**
244
 
         * Internal initialization implementation for BaseCore
245
 
         *
246
 
         * @method _baseInit
247
 
         * @private
248
 
         */
249
 
        _baseInit: function(cfg) {
250
 
            this._initHierarchy(cfg);
251
 
 
252
 
            if (this._initPlugins) {
253
 
                // Need to initPlugins manually, to handle constructor parsing, static Plug parsing
254
 
                this._initPlugins(cfg);
255
 
            }
256
 
            this._set(INITIALIZED, true);
257
 
        },
258
 
 
259
 
        /**
260
 
         * Destroy lifecycle method. Invokes destructors for the class hierarchy.
261
 
         *
262
 
         * @method destroy
263
 
         * @return {BaseCore} A reference to this object
264
 
         * @chainable
265
 
         */
266
 
        destroy: function() {
267
 
            this._baseDestroy();
268
 
            return this;
269
 
        },
270
 
 
271
 
        /**
272
 
         * Internal destroy implementation for BaseCore
273
 
         *
274
 
         * @method _baseDestroy
275
 
         * @private
276
 
         */
277
 
        _baseDestroy : function() {
278
 
            if (this._destroyPlugins) {
279
 
                this._destroyPlugins();
280
 
            }
281
 
            this._destroyHierarchy();
282
 
            this._set(DESTROYED, true);
283
 
        },
284
 
 
285
 
        /**
286
 
         * Returns the class hierarchy for this object, with BaseCore being the last class in the array.
287
 
         *
288
 
         * @method _getClasses
289
 
         * @protected
290
 
         * @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
291
 
         * This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the 
292
 
         * cached value.
293
 
         */
294
 
        _getClasses : function() {
295
 
            if (!this._classes) {
296
 
                this._initHierarchyData();
297
 
            }
298
 
            return this._classes;
299
 
        },
300
 
 
301
 
        /**
302
 
         * Returns an aggregated set of attribute configurations, by traversing 
303
 
         * the class hierarchy.
304
 
         *
305
 
         * @method _getAttrCfgs
306
 
         * @protected
307
 
         * @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
308
 
         * This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
309
 
         * the cached value.
310
 
         */
311
 
        _getAttrCfgs : function() {
312
 
            if (!this._attrs) {
313
 
                this._initHierarchyData();
314
 
            }
315
 
            return this._attrs;
316
 
        },
317
 
 
318
 
        /**
319
 
         * A helper method used when processing ATTRS across the class hierarchy during 
320
 
         * initialization. Returns a disposable object with the attributes defined for 
321
 
         * the provided class, extracted from the set of all attributes passed in.
322
 
         *
323
 
         * @method _filterAttrCfs
324
 
         * @private
325
 
         *
326
 
         * @param {Function} clazz The class for which the desired attributes are required.
327
 
         * @param {Object} allCfgs The set of all attribute configurations for this instance. 
328
 
         * Attributes will be removed from this set, if they belong to the filtered class, so
329
 
         * that by the time all classes are processed, allCfgs will be empty.
330
 
         * 
331
 
         * @return {Object} The set of attributes belonging to the class passed in, in the form
332
 
         * of an object with attribute name/configuration pairs.
333
 
         */
334
 
        _filterAttrCfgs : function(clazz, allCfgs) {
335
 
            var cfgs = null, attr, attrs = clazz.ATTRS;
336
 
 
337
 
            if (attrs) {
338
 
                for (attr in attrs) {
339
 
                    if (allCfgs[attr]) {
340
 
                        cfgs = cfgs || {};
341
 
                        cfgs[attr] = allCfgs[attr];
342
 
                        allCfgs[attr] = null;
343
 
                    }
344
 
                }
345
 
            }
346
 
 
347
 
            return cfgs;
348
 
        },
349
 
 
350
 
        /**
351
 
         * @method _filterAdHocAttrs
352
 
         * @private
353
 
         *
354
 
         * @param {Object} allAttrs The set of all attribute configurations for this instance. 
355
 
         * Attributes will be removed from this set, if they belong to the filtered class, so
356
 
         * that by the time all classes are processed, allCfgs will be empty.
357
 
         * @param {Object} userVals The config object passed in by the user, from which adhoc attrs are to be filtered.
358
 
         * @return {Object} The set of adhoc attributes passed in, in the form
359
 
         * of an object with attribute name/configuration pairs.
360
 
         */
361
 
        _filterAdHocAttrs : function(allAttrs, userVals) {
362
 
            var adHocs,
363
 
                nonAttrs = this._nonAttrs,
364
 
                attr;
365
 
 
366
 
            if (userVals) {
367
 
                adHocs = {};
368
 
                for (attr in userVals) {
369
 
                    if (!allAttrs[attr] && !nonAttrs[attr] && userVals.hasOwnProperty(attr)) {
370
 
                        adHocs[attr] = {
371
 
                            value:userVals[attr]
372
 
                        };
373
 
                    }
374
 
                }
375
 
            }
376
 
 
377
 
            return adHocs;
378
 
        },
379
 
 
380
 
        /**
381
 
         * A helper method used by _getClasses and _getAttrCfgs, which determines both
382
 
         * the array of classes and aggregate set of attribute configurations
383
 
         * across the class hierarchy for the instance.
384
 
         *
385
 
         * @method _initHierarchyData
386
 
         * @private
387
 
         */
388
 
        _initHierarchyData : function() {
389
 
            var c = this.constructor,
390
 
                i,
391
 
                l,
392
 
                nonAttrsCfg,
393
 
                nonAttrs = (this._allowAdHocAttrs) ? {} : null,
394
 
                classes = [],
395
 
                attrs = [];
396
 
 
397
 
            while (c) {
398
 
                // Add to classes
399
 
                classes[classes.length] = c;
400
 
 
401
 
                // Add to attributes
402
 
                if (c.ATTRS) {
403
 
                    attrs[attrs.length] = c.ATTRS;
404
 
                }
405
 
 
406
 
                if (this._allowAdHocAttrs) {
407
 
                    nonAttrsCfg = c._NON_ATTRS_CFG; 
408
 
                    if (nonAttrsCfg) {
409
 
                        for (i = 0, l = nonAttrsCfg.length; i < l; i++) {
410
 
                            nonAttrs[nonAttrsCfg[i]] = true;
411
 
                        }
412
 
                    }
413
 
                }
414
 
 
415
 
                c = c.superclass ? c.superclass.constructor : null;
416
 
            }
417
 
 
418
 
            this._classes = classes;
419
 
            this._nonAttrs = nonAttrs;
420
 
            this._attrs = this._aggregateAttrs(attrs);
421
 
        },
422
 
 
423
 
        /**
424
 
         * Utility method to define the attribute hash used to filter/whitelist property mixes for 
425
 
         * this class. 
426
 
         * 
427
 
         * @method _attrCfgHash
428
 
         * @private
429
 
         */
430
 
        _attrCfgHash: function() {
431
 
            return BaseCore._ATTR_CFG_HASH;
432
 
        },
433
 
 
434
 
        /**
435
 
         * A helper method, used by _initHierarchyData to aggregate 
436
 
         * attribute configuration across the instances class hierarchy.
437
 
         *
438
 
         * The method will protect the attribute configuration value to protect the statically defined 
439
 
         * default value in ATTRS if required (if the value is an object literal, array or the 
440
 
         * attribute configuration has cloneDefaultValue set to shallow or deep).
441
 
         *
442
 
         * @method _aggregateAttrs
443
 
         * @private
444
 
         * @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy 
445
 
         * (subclass first, Base last)
446
 
         * @return {Object} The aggregate set of ATTRS definitions for the instance
447
 
         */
448
 
        _aggregateAttrs : function(allAttrs) {
449
 
            var attr,
450
 
                attrs,
451
 
                cfg,
452
 
                val,
453
 
                path,
454
 
                i,
455
 
                clone,
456
 
                cfgPropsHash = this._attrCfgHash(),
457
 
                aggAttrs = {};
458
 
 
459
 
            if (allAttrs) {
460
 
                for (i = allAttrs.length-1; i >= 0; --i) {
461
 
                    attrs = allAttrs[i];
462
 
 
463
 
                    for (attr in attrs) {
464
 
                        if (attrs.hasOwnProperty(attr)) {
465
 
 
466
 
                            // Protect config passed in
467
 
                            //cfg = Y.mix({}, attrs[attr], true, cfgProps);
468
 
                            //cfg = Y.Object(attrs[attr]);
469
 
                            cfg = _wlmix({}, attrs[attr], cfgPropsHash);
470
 
 
471
 
                            val = cfg.value;
472
 
                            clone = cfg.cloneDefaultValue;
473
 
 
474
 
                            if (val) {
475
 
                                if ( (clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val))) || clone === DEEP || clone === true) {
476
 
                                    Y.log('Cloning default value for attribute:' + attr, 'info', 'base');
477
 
                                    cfg.value = Y.clone(val);
478
 
                                } else if (clone === SHALLOW) {
479
 
                                    Y.log('Merging default value for attribute:' + attr, 'info', 'base');
480
 
                                    cfg.value = Y.merge(val);
481
 
                                }
482
 
                                // else if (clone === false), don't clone the static default value. 
483
 
                                // It's intended to be used by reference.
484
 
                            }
485
 
 
486
 
                            path = null;
487
 
                            if (attr.indexOf(DOT) !== -1) {
488
 
                                path = attr.split(DOT);
489
 
                                attr = path.shift();
490
 
                            }
491
 
 
492
 
                            if (path && aggAttrs[attr] && aggAttrs[attr].value) {
493
 
                                O.setValue(aggAttrs[attr].value, path, val);
494
 
                            } else if (!path) {
495
 
                                if (!aggAttrs[attr]) {
496
 
                                    aggAttrs[attr] = cfg;
497
 
                                } else {
498
 
                                    _wlmix(aggAttrs[attr], cfg, cfgPropsHash);
499
 
                                }
500
 
                            }
501
 
                        }
502
 
                    }
503
 
                }
504
 
            }
505
 
 
506
 
            return aggAttrs;
507
 
        },
508
 
 
509
 
        /**
510
 
         * Initializes the class hierarchy for the instance, which includes 
511
 
         * initializing attributes for each class defined in the class's 
512
 
         * static <a href="#property_BaseCore.ATTRS">ATTRS</a> property and 
513
 
         * invoking the initializer method on the prototype of each class in the hierarchy.
514
 
         *
515
 
         * @method _initHierarchy
516
 
         * @param {Object} userVals Object with configuration property name/value pairs
517
 
         * @private
518
 
         */
519
 
        _initHierarchy : function(userVals) {
520
 
            var lazy = this._lazyAddAttrs,
521
 
                constr,
522
 
                constrProto,
523
 
                ci,
524
 
                ei,
525
 
                el,
526
 
                extProto,
527
 
                exts,
528
 
                classes = this._getClasses(),
529
 
                attrCfgs = this._getAttrCfgs(),
530
 
                cl = classes.length - 1;
531
 
 
532
 
            for (ci = cl; ci >= 0; ci--) {
533
 
 
534
 
                constr = classes[ci];
535
 
                constrProto = constr.prototype;
536
 
                exts = constr._yuibuild && constr._yuibuild.exts; 
537
 
 
538
 
                if (exts) {
539
 
                    for (ei = 0, el = exts.length; ei < el; ei++) {
540
 
                        exts[ei].apply(this, arguments);
541
 
                    }
542
 
                }
543
 
 
544
 
                this.addAttrs(this._filterAttrCfgs(constr, attrCfgs), userVals, lazy);
545
 
 
546
 
                if (this._allowAdHocAttrs && ci === cl) {                
547
 
                    this.addAttrs(this._filterAdHocAttrs(attrCfgs, userVals), userVals, lazy);
548
 
                }
549
 
 
550
 
                // Using INITIALIZER in hasOwnProperty check, for performance reasons (helps IE6 avoid GC thresholds when
551
 
                // referencing string literals). Not using it in apply, again, for performance "." is faster. 
552
 
                if (constrProto.hasOwnProperty(INITIALIZER)) {
553
 
                    constrProto.initializer.apply(this, arguments);
554
 
                }
555
 
 
556
 
                if (exts) {
557
 
                    for (ei = 0; ei < el; ei++) {
558
 
                        extProto = exts[ei].prototype;
559
 
                        if (extProto.hasOwnProperty(INITIALIZER)) {
560
 
                            extProto.initializer.apply(this, arguments);
561
 
                        }
562
 
                    }
563
 
                }
564
 
            }
565
 
        },
566
 
 
567
 
        /**
568
 
         * Destroys the class hierarchy for this instance by invoking
569
 
         * the destructor method on the prototype of each class in the hierarchy.
570
 
         *
571
 
         * @method _destroyHierarchy
572
 
         * @private
573
 
         */
574
 
        _destroyHierarchy : function() {
575
 
            var constr,
576
 
                constrProto,
577
 
                ci, cl, ei, el, exts, extProto,
578
 
                classes = this._getClasses();
579
 
 
580
 
            for (ci = 0, cl = classes.length; ci < cl; ci++) {
581
 
                constr = classes[ci];
582
 
                constrProto = constr.prototype;
583
 
                exts = constr._yuibuild && constr._yuibuild.exts; 
584
 
 
585
 
                if (exts) {
586
 
                    for (ei = 0, el = exts.length; ei < el; ei++) {
587
 
                        extProto = exts[ei].prototype;
588
 
                        if (extProto.hasOwnProperty(DESTRUCTOR)) {
589
 
                            extProto.destructor.apply(this, arguments);
590
 
                        }
591
 
                    }
592
 
                }
593
 
 
594
 
                if (constrProto.hasOwnProperty(DESTRUCTOR)) {
595
 
                    constrProto.destructor.apply(this, arguments);
596
 
                }
597
 
            }
598
 
        },
599
 
 
600
 
        /**
601
 
         * Default toString implementation. Provides the constructor NAME
602
 
         * and the instance guid, if set.
603
 
         *
604
 
         * @method toString
605
 
         * @return {String} String representation for this object
606
 
         */
607
 
        toString: function() {
608
 
            return this.name + "[" + Y.stamp(this, true) + "]";
609
 
        }
610
 
    };
611
 
 
612
 
    // Straightup augment, no wrapper functions
613
 
    Y.mix(BaseCore, AttributeCore, false, null, 1);
614
 
 
615
 
    // Fix constructor
616
 
    BaseCore.prototype.constructor = BaseCore;
617
 
 
618
 
    Y.BaseCore = BaseCore;
619
 
 
620
 
 
621
 
}, '3.5.1' ,{requires:['attribute-core']});