src/cm/media/js/lib/yui/yui_3.0.0b1/build/base/base-debug.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     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: 3.0.0b1
       
     6 build: 1163
       
     7 */
       
     8 YUI.add('base-base', function(Y) {
       
     9 
       
    10     /**
       
    11      * <p>
       
    12      * An augmentable class, which provides the augmented class with the ability to host plugins.
       
    13      * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can 
       
    14      * be used to add or remove plugins from instances of the class.
       
    15      * </p>
       
    16      *
       
    17      * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
       
    18      * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method. 
       
    19      * 
       
    20      * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
       
    21      * <xmp>
       
    22      * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
       
    23      * </xmp>
       
    24      * </p>
       
    25      * <p>
       
    26      * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a> 
       
    27      * methods should be invoked by the host class at the appropriate point in the host's lifecyle. This is done by default for 
       
    28      * the Base class, so developers extending Base or Widget don't need to do anything to enable plugin support.
       
    29      * </p>
       
    30      *
       
    31      * @class Plugin.Host
       
    32      */
       
    33 
       
    34     var L = Y.Lang;
       
    35 
       
    36     function PluginHost(config) {
       
    37         this._plugins = {};
       
    38     }
       
    39 
       
    40     PluginHost.prototype = {
       
    41 
       
    42         /**
       
    43          * Adds a plugin to the host object. This will instantiate the 
       
    44          * plugin and attach it to the configured namespace on the host object.
       
    45          *
       
    46          * @method plug
       
    47          * @chainable
       
    48          * @param p {Function | Object |Array} Accepts the plugin class, or an 
       
    49          * object with a "fn" property specifying the plugin class and 
       
    50          * a "cfg" property specifying the configuration for the Plugin.
       
    51          * <p>
       
    52          * Additionally an Array can also be passed in, with the above function or 
       
    53          * object values, allowing the user to add multiple plugins in a single call.
       
    54          * </p>
       
    55          * @param config (Optional) If the first argument is the plugin class, the second argument
       
    56          * can be the configuration for the plugin.
       
    57          * @return {Base} A reference to the host object
       
    58          */
       
    59 
       
    60         plug: function(p, config) {
       
    61             if (p) {
       
    62                 if (L.isFunction(p)) {
       
    63                     this._plug(p, config);
       
    64                 } else if (L.isArray(p)) {
       
    65                     for (var i = 0, ln = p.length; i < ln; i++) {
       
    66                         this.plug(p[i]);
       
    67                     }
       
    68                 } else {
       
    69                     this._plug(p.fn, p.cfg);
       
    70                 }
       
    71             }
       
    72             return this;
       
    73         },
       
    74 
       
    75         /**
       
    76          * Removes a plugin from the host object. This will destroy the 
       
    77          * plugin instance and delete the namepsace from the host object. 
       
    78          *
       
    79          * @method unplug
       
    80          * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
       
    81          * all registered plugins are unplugged.
       
    82          * @return {Base} A reference to the host object
       
    83          * @chainable
       
    84          */
       
    85         unplug: function(plugin) {
       
    86             if (plugin) {
       
    87                 this._unplug(plugin);
       
    88             } else {
       
    89                 var ns;
       
    90                 for (ns in this._plugins) {
       
    91                     if (this._plugins.hasOwnProperty(ns)) {
       
    92                         this._unplug(ns);
       
    93                     }
       
    94                 }
       
    95             }
       
    96             return this;
       
    97         },
       
    98 
       
    99         /**
       
   100          * Determines if a plugin has plugged into this host.
       
   101          *
       
   102          * @method hasPlugin
       
   103          * @param {String} ns The plugin's namespace
       
   104          * @return {boolean} returns true, if the plugin has been plugged into this host, false otherwise.
       
   105          */
       
   106         hasPlugin : function(ns) {
       
   107             return (this._plugins[ns] && this[ns]);
       
   108         },
       
   109 
       
   110         /**
       
   111          * Initializes static plugins registered on the host (using the
       
   112          * Base.plug static method) and any plugins passed to the 
       
   113          * instance through the "plugins" configuration property.
       
   114          *
       
   115          * @method _initPlugins
       
   116          * @param {Config} config The configuration object with property name/value pairs.
       
   117          * @private
       
   118          */
       
   119         _initPlugins: function(config) {
       
   120 
       
   121             // Class Configuration
       
   122             var classes = this._getClasses(),
       
   123                 plug = [],
       
   124                 unplug = {},
       
   125                 constructor, i, classPlug, classUnplug, pluginClassName;
       
   126 
       
   127             //TODO: Room for optimization. Can we apply statically/unplug in same pass?
       
   128             for (i = classes.length - 1; i >= 0; i--) {
       
   129                 constructor = classes[i];
       
   130 
       
   131                 classUnplug = constructor._UNPLUG;
       
   132                 if (classUnplug) {
       
   133                     // subclasses over-write
       
   134                     Y.mix(unplug, classUnplug, true);
       
   135                 }
       
   136 
       
   137                 classPlug = constructor._PLUG;
       
   138                 if (classPlug) {
       
   139                     // subclasses over-write
       
   140                     Y.mix(plug, classPlug, true);
       
   141                 }
       
   142             }
       
   143     
       
   144             for (pluginClassName in plug) {
       
   145                 if (plug.hasOwnProperty(pluginClassName)) {
       
   146                     if (!unplug[pluginClassName]) {
       
   147                         this.plug(plug[pluginClassName]);
       
   148                     }
       
   149                 }
       
   150             }
       
   151     
       
   152             // User Configuration
       
   153             if (config && config.plugins) {
       
   154                 this.plug(config.plugins);
       
   155             }
       
   156         },
       
   157 
       
   158         /**
       
   159          * Unplugs and destroys all plugins on the host
       
   160          * @method _destroyPlugins
       
   161          * @private
       
   162          */
       
   163         _destroyPlugins: function() {
       
   164             this._unplug();
       
   165         },
       
   166 
       
   167         /**
       
   168          * Private method used to instantiate and attach plugins to the host
       
   169          *
       
   170          * @method _plug
       
   171          * @param {Function} PluginClass The plugin class to instantiate
       
   172          * @param {Object} config The configuration object for the plugin
       
   173          * @private
       
   174          */
       
   175         _plug: function(PluginClass, config) {
       
   176             if (PluginClass && PluginClass.NS) {
       
   177                 var ns = PluginClass.NS;
       
   178     
       
   179                 config = config || {};
       
   180                 config.host = this;
       
   181     
       
   182                 if (this.hasPlugin(ns)) {
       
   183                     // Update config
       
   184                     this[ns].setAttrs(config);
       
   185                 } else {
       
   186                     // Create new instance
       
   187                     this[ns] = new PluginClass(config);
       
   188                     this._plugins[ns] = PluginClass;
       
   189                 }
       
   190             }
       
   191         },
       
   192 
       
   193         /**
       
   194          * Unplugs and destroys a plugin already instantiated with the host.
       
   195          *
       
   196          * @method _unplug
       
   197          * @private
       
   198          * @param {String | Function} plugin The namespace for the plugin, or a plugin class with the static NS property defined.
       
   199          */
       
   200         _unplug : function(plugin) {
       
   201             var ns = plugin, 
       
   202                 plugins = this._plugins;
       
   203     
       
   204             if (L.isFunction(plugin)) {
       
   205                 ns = plugin.NS;
       
   206                 if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
       
   207                     ns = null;
       
   208                 }
       
   209             }
       
   210     
       
   211             if (ns) {
       
   212                 if (this[ns]) {
       
   213                     this[ns].destroy();
       
   214                     delete this[ns];
       
   215                 }
       
   216                 if (plugins[ns]) {
       
   217                     delete plugins[ns];
       
   218                 }
       
   219             }
       
   220         }
       
   221     };
       
   222     
       
   223     /**
       
   224      * Registers plugins to be instantiated at the class level (plugins 
       
   225      * which should be plugged into every instance of the class by default).
       
   226      *
       
   227      * @method Plugin.Host.plug
       
   228      * @static
       
   229      *
       
   230      * @param {Function} hostClass The host class on which to register the plugins
       
   231      * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
   232      * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
   233      */
       
   234     PluginHost.plug = function(hostClass, plugin, config) {
       
   235         // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
       
   236         var p, i, l, name;
       
   237     
       
   238         if (hostClass !== Y.Base) {
       
   239             hostClass._PLUG = hostClass._PLUG || {};
       
   240     
       
   241             if (!L.isArray(plugin)) {
       
   242                 if (config) {
       
   243                     plugin = {fn:plugin, cfg:config};
       
   244                 }
       
   245                 plugin = [plugin];
       
   246             }
       
   247     
       
   248             for (i = 0, l = plugin.length; i < l;i++) {
       
   249                 p = plugin[i];
       
   250                 name = p.NAME || p.fn.NAME;
       
   251                 hostClass._PLUG[name] = p;
       
   252             }
       
   253         }
       
   254     };
       
   255 
       
   256     /**
       
   257      * Unregisters any class level plugins which have been registered by the host class, or any
       
   258      * other class in the hierarchy.
       
   259      *
       
   260      * @method Plugin.Host.unplug
       
   261      * @static
       
   262      *
       
   263      * @param {Function} hostClass The host class from which to unregister the plugins
       
   264      * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
   265      */
       
   266     PluginHost.unplug = function(hostClass, plugin) {
       
   267         var p, i, l, name;
       
   268     
       
   269         if (hostClass !== Y.Base) {
       
   270             hostClass._UNPLUG = hostClass._UNPLUG || {};
       
   271     
       
   272             if (!L.isArray(plugin)) {
       
   273                 plugin = [plugin];
       
   274             }
       
   275     
       
   276             for (i = 0, l = plugin.length; i < l; i++) {
       
   277                 p = plugin[i];
       
   278                 name = p.NAME;
       
   279                 if (!hostClass._PLUG[name]) {
       
   280                     hostClass._UNPLUG[name] = p;
       
   281                 } else {
       
   282                     delete hostClass._PLUG[name];
       
   283                 }
       
   284             }
       
   285         }
       
   286     };
       
   287 
       
   288     Y.namespace("Plugin").Host = PluginHost;
       
   289 
       
   290     /**
       
   291      * The base module provides the Base class, which objects requiring attribute and custom event support can extend. 
       
   292      * The module also provides two ways to reuse code - An augmentable Plugin.Host interface which provides plugin support 
       
   293      * (which is augmented to the Base class) and Base.build which provides a way to 
       
   294      * build custom classes using extensions.
       
   295      *
       
   296      * @module base
       
   297      */
       
   298 
       
   299     /**
       
   300      * The base-base submodule provides the Base class and augmentable Plugin.Host implementation, 
       
   301      * without the extension support provided by Base.build.
       
   302      *
       
   303      * @module base
       
   304      * @submodule base-base
       
   305      */
       
   306     var O = Y.Object,
       
   307         DOT = ".",
       
   308         DESTROY = "destroy",
       
   309         INIT = "init",
       
   310         INITIALIZED = "initialized",
       
   311         DESTROYED = "destroyed",
       
   312         INITIALIZER = "initializer",
       
   313         OBJECT_CONSTRUCTOR = Object.prototype.constructor,
       
   314         DEEP = "deep",
       
   315         SHALLOW = "shallow",
       
   316         VALUE = "value",
       
   317         DESTRUCTOR = "destructor";
       
   318 
       
   319     /**
       
   320      * <p>
       
   321      * A base class which objects requiring attributes and custom event support can 
       
   322      * extend. Base also handles the chaining of initializer and destructor methods across 
       
   323      * the hierarchy as part of object construction and destruction. Additionally, attributes configured 
       
   324      * through the static <a href="#property_Base.ATTRS">ATTRS</a> property for each class 
       
   325      * in the hierarchy will be initialized by Base.
       
   326      * </p>
       
   327      *
       
   328      * <p>
       
   329      * The static <a href="#property_Base.NAME">NAME</a> property of each class extending 
       
   330      * from Base will be used as the identifier for the class, and is used by Base to prefix 
       
   331      * all events fired by instances of that class.
       
   332      * </p>
       
   333      * @class Base
       
   334      * @constructor
       
   335      * @uses Attribute
       
   336      * @uses Plugin.Host
       
   337      *
       
   338      * @param {Object} config Object with configuration property name/value pairs
       
   339      */
       
   340     function Base() {
       
   341         Y.log('constructor called', 'life', 'base');
       
   342 
       
   343         Y.Attribute.call(this);
       
   344         Y.Plugin.Host.call(this);
       
   345 
       
   346         this._silentInit = this._silentInit || false;
       
   347         if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
       
   348 
       
   349         this.init.apply(this, arguments);
       
   350     }
       
   351 
       
   352     /**
       
   353      * The list of properties which can be configured for 
       
   354      * each attribute (e.g. setter, getter, writeOnce, readOnly etc.)
       
   355      *
       
   356      * @property Base._ATTR_CFG
       
   357      * @type Array
       
   358      * @static
       
   359      * @private
       
   360      */
       
   361     Base._ATTR_CFG = Y.Attribute._ATTR_CFG.concat("cloneDefaultValue");
       
   362 
       
   363     /**
       
   364      * <p>
       
   365      * The string to be used to identify instances of 
       
   366      * this class, for example in prefixing events.
       
   367      * </p>
       
   368      * <p>
       
   369      * Classes extending Base, should define their own
       
   370      * static NAME property, which should be camelCase by
       
   371      * convention (e.g. MyClass.NAME = "myClass";).
       
   372      * </p>
       
   373      * @property Base.NAME
       
   374      * @type String
       
   375      * @static
       
   376      */
       
   377     Base.NAME = 'base';
       
   378 
       
   379     /**
       
   380      * The default set of attributes which will be available for instances of this class, and 
       
   381      * their configuration. In addition to the configuration properties listed by 
       
   382      * Attribute's <a href="Attribute.html#method_addAttr">addAttr</a> method, the attribute 
       
   383      * can also be configured with a "cloneDefaultValue" property, which defines how the statically
       
   384      * defined value field should be protected ("shallow", "deep" and false are supported values). 
       
   385      *
       
   386      * By default if the value is an object literal or an array it will be "shallow" cloned, to 
       
   387      * protect the default value.
       
   388      *
       
   389      * @property Base.ATTRS
       
   390      * @type Object
       
   391      * @static
       
   392      */
       
   393     Base.ATTRS = {
       
   394         /**
       
   395          * Flag indicating whether or not this object
       
   396          * has been through the init lifecycle phase.
       
   397          *
       
   398          * @attribute initialized
       
   399          * @readonly
       
   400          * @default false
       
   401          * @type boolean
       
   402          */
       
   403         initialized: {
       
   404             readOnly:true,
       
   405             value:false
       
   406         },
       
   407 
       
   408         /**
       
   409          * Flag indicating whether or not this object
       
   410          * has been through the destroy lifecycle phase.
       
   411          *
       
   412          * @attribute destroyed
       
   413          * @readonly
       
   414          * @default false
       
   415          * @type boolean
       
   416          */
       
   417         destroyed: {
       
   418             readOnly:true,
       
   419             value:false
       
   420         }
       
   421     };
       
   422 
       
   423     Base.prototype = {
       
   424 
       
   425         /**
       
   426          * Init lifecycle method, invoked during construction.
       
   427          * Fires the init event prior to setting up attributes and 
       
   428          * invoking initializers for the class hierarchy.
       
   429          *
       
   430          * @method init
       
   431          * @final
       
   432          * @chainable
       
   433          * @param {Object} config Object with configuration property name/value pairs
       
   434          * @return {Base} A reference to this object
       
   435          */
       
   436         init: function(config) {
       
   437             Y.log('init called', 'life', 'base');
       
   438 
       
   439             /**
       
   440              * The string used to identify the class of this object.
       
   441              *
       
   442              * @deprecated Use this.constructor.NAME
       
   443              * @property name
       
   444              * @type String
       
   445              */
       
   446             this._yuievt.config.prefix = this.name = this.constructor.NAME;
       
   447 
       
   448             /**
       
   449              * <p>
       
   450              * Lifecycle event for the init phase, fired prior to initialization. 
       
   451              * Invoking the preventDefault() method on the event object provided 
       
   452              * to subscribers will prevent initialization from occuring.
       
   453              * </p>
       
   454              * <p>
       
   455              * Subscribers to the "after" momemt of this event, will be notified
       
   456              * after initialization of the object is complete (and therefore
       
   457              * cannot prevent initialization).
       
   458              * </p>
       
   459              *
       
   460              * @event init
       
   461              * @preventable _defInitFn
       
   462              * @param {EventFacade} e Event object, with a cfg property which 
       
   463              * refers to the configuration object passed to the constructor.
       
   464              */
       
   465             if (!this._silentInit) {
       
   466                 this.publish(INIT, {
       
   467                     queuable:false,
       
   468                     defaultFn:this._defInitFn
       
   469                 });
       
   470             }
       
   471 
       
   472             if (config) {
       
   473                 if (config.on) {
       
   474                     this.on(config.on);
       
   475                 }
       
   476                 if (config.after) {
       
   477                     this.after(config.after);
       
   478                 }
       
   479             }
       
   480 
       
   481             if (!this._silentInit) {
       
   482                 this.fire(INIT, {cfg: config});
       
   483             } else {
       
   484                 this._defInitFn({cfg: config});
       
   485             }
       
   486 
       
   487             return this;
       
   488         },
       
   489 
       
   490         /**
       
   491          * <p>
       
   492          * Destroy lifecycle method. Fires the destroy
       
   493          * event, prior to invoking destructors for the
       
   494          * class hierarchy.
       
   495          * </p>
       
   496          * <p>
       
   497          * Subscribers to the destroy
       
   498          * event can invoke preventDefault on the event object, to prevent destruction
       
   499          * from proceeding.
       
   500          * </p>
       
   501          * @method destroy
       
   502          * @return {Base} A reference to this object
       
   503          * @final
       
   504          * @chainable
       
   505          */
       
   506         destroy: function() {
       
   507             Y.log('destroy called', 'life', 'base');
       
   508 
       
   509             /**
       
   510              * <p>
       
   511              * Lifecycle event for the destroy phase, 
       
   512              * fired prior to destruction. Invoking the preventDefault 
       
   513              * method on the event object provided to subscribers will 
       
   514              * prevent destruction from proceeding.
       
   515              * </p>
       
   516              * <p>
       
   517              * Subscribers to the "after" moment of this event, will be notified
       
   518              * after destruction is complete (and as a result cannot prevent
       
   519              * destruction).
       
   520              * </p>
       
   521              * @event destroy
       
   522              * @preventable _defDestroyFn
       
   523              * @param {EventFacade} e Event object
       
   524              */
       
   525             this.publish(DESTROY, {
       
   526                 queuable:false,
       
   527                 defaultFn: this._defDestroyFn
       
   528             });
       
   529             this.fire(DESTROY);
       
   530             return this;
       
   531         },
       
   532 
       
   533         /**
       
   534          * Default init event handler
       
   535          *
       
   536          * @method _defInitFn
       
   537          * @param {EventFacade} e Event object, with a cfg property which 
       
   538          * refers to the configuration object passed to the constructor.
       
   539          * @protected
       
   540          */
       
   541         _defInitFn : function(e) {
       
   542             this._initHierarchy(e.cfg);
       
   543             this._initPlugins(e.cfg);
       
   544 
       
   545             if (!this._silentInit) {
       
   546                 this._set(INITIALIZED, true);
       
   547             } else {
       
   548                 this._conf.add(INITIALIZED, VALUE, true);
       
   549             }
       
   550         },
       
   551 
       
   552         /**
       
   553          * Default destroy event handler
       
   554          *
       
   555          * @method _defDestroyFn
       
   556          * @param {EventFacade} e Event object
       
   557          * @protected
       
   558          */
       
   559         _defDestroyFn : function(e) {
       
   560             this._destroyHierarchy();
       
   561             this._destroyPlugins();
       
   562             this._set(DESTROYED, true);
       
   563         },
       
   564 
       
   565         /**
       
   566          * Returns the class hierarchy for this object, with Base being the last class in the array.
       
   567          *
       
   568          * @method _getClasses
       
   569          * @protected
       
   570          * @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
       
   571          * This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the 
       
   572          * cached value.
       
   573          */
       
   574         _getClasses : function() {
       
   575             if (!this._classes) {
       
   576                 this._initHierarchyData();
       
   577             }
       
   578             return this._classes;
       
   579         },
       
   580 
       
   581         /**
       
   582          * Returns an aggregated set of attribute configurations, by traversing the class hierarchy.
       
   583          *
       
   584          * @method _getAttrCfgs
       
   585          * @protected
       
   586          * @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
       
   587          * This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
       
   588          * the cached value.
       
   589          */
       
   590         _getAttrCfgs : function() {
       
   591             if (!this._attrs) {
       
   592                 this._initHierarchyData();
       
   593             }
       
   594             return this._attrs;
       
   595         },
       
   596 
       
   597         /**
       
   598          * A helper method used when processing ATTRS across the class hierarchy during 
       
   599          * initialization. Returns a disposable object with the attributes defined for 
       
   600          * the provided class, extracted from the set of all attributes passed in .
       
   601          *
       
   602          * @method _filterAttrCfs
       
   603          * @private
       
   604          *
       
   605          * @param {Function} clazz The class for which the desired attributes are required.
       
   606          * @param {Object} allCfgs The set of all attribute configurations for this instance. 
       
   607          * Attributes will be removed from this set, if they belong to the filtered class, so
       
   608          * that by the time all classes are processed, allCfgs will be empty.
       
   609          * 
       
   610          * @return {Object} The set of attributes belonging to the class passed in, in the form
       
   611          * of an object with attribute name/configuration pairs.
       
   612          */
       
   613         _filterAttrCfgs : function(clazz, allCfgs) {
       
   614             var cfgs = null, attr, attrs = clazz.ATTRS;
       
   615 
       
   616             if (attrs) {
       
   617                 for (attr in attrs) {
       
   618                     if (attrs.hasOwnProperty(attr) && allCfgs[attr]) {
       
   619                         cfgs = cfgs || {};
       
   620                         cfgs[attr] = allCfgs[attr];
       
   621                         delete allCfgs[attr];
       
   622                     }
       
   623                 }
       
   624             }
       
   625 
       
   626             return cfgs;
       
   627         },
       
   628 
       
   629         /**
       
   630          * A helper method used by _getClasses and _getAttrCfgs, which determines both
       
   631          * the array of classes and aggregate set of attribute configurations
       
   632          * across the class hierarchy for the instance.
       
   633          * 
       
   634          * @method _initHierarchyData
       
   635          * @private
       
   636          */
       
   637         _initHierarchyData : function() {
       
   638             var c = this.constructor, 
       
   639                 classes = [],
       
   640                 attrs = [];
       
   641 
       
   642             while (c) {
       
   643                 // Add to classes
       
   644                 classes[classes.length] = c;
       
   645 
       
   646                 // Add to attributes
       
   647                 if (c.ATTRS) {
       
   648                     attrs[attrs.length] = c.ATTRS;
       
   649                 }
       
   650                 c = c.superclass ? c.superclass.constructor : null;
       
   651             }
       
   652 
       
   653             this._classes = classes;
       
   654             this._attrs = this._aggregateAttrs(attrs);
       
   655         },
       
   656 
       
   657         /**
       
   658          * A helper method, used by _initHierarchyData to aggregate 
       
   659          * attribute configuration across the instances class hierarchy.
       
   660          *
       
   661          * The method will potect the attribute configuration value to protect the statically defined 
       
   662          * default value in ATTRS if required (if the value is an object literal, array or the 
       
   663          * attribute configuration has cloneDefaultValue set to shallow or deep).
       
   664          *
       
   665          * @method _aggregateAttrs
       
   666          * @private
       
   667          * @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy 
       
   668          * (subclass first, Base last)
       
   669          * @return {Object} The aggregate set of ATTRS definitions for the instance
       
   670          */
       
   671         _aggregateAttrs : function(allAttrs) {
       
   672             var attr, 
       
   673                 attrs, 
       
   674                 cfg, 
       
   675                 val, 
       
   676                 path, 
       
   677                 i, 
       
   678                 clone, 
       
   679                 cfgProps = Base._ATTR_CFG,
       
   680                 aggAttrs = {};
       
   681 
       
   682             if (allAttrs) {
       
   683                 for (i = allAttrs.length-1; i >= 0; --i) {
       
   684                     attrs = allAttrs[i];
       
   685 
       
   686                     for (attr in attrs) {
       
   687                         if (attrs.hasOwnProperty(attr)) {
       
   688 
       
   689                             // Protect config passed in
       
   690                             cfg = Y.mix({}, attrs[attr], true, cfgProps);
       
   691 
       
   692                             val = cfg.value;
       
   693                             clone = cfg.cloneDefaultValue;
       
   694 
       
   695                             if (val) {
       
   696                                 if ( (clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val))) || clone === DEEP || clone === true) {
       
   697                                     Y.log('Cloning default value for attribute:' + attr, 'info', 'base');
       
   698                                     cfg.value = Y.clone(val);
       
   699                                 } else if (clone === SHALLOW) {
       
   700                                     Y.log('Merging default value for attribute:' + attr, 'info', 'base');
       
   701                                     cfg.value = Y.merge(val);
       
   702                                 }
       
   703                                 // else if (clone === false), don't clone the static default value. 
       
   704                                 // It's intended to be used by reference.
       
   705                             }
       
   706 
       
   707                             path = null;
       
   708                             if (attr.indexOf(DOT) !== -1) {
       
   709                                 path = attr.split(DOT);
       
   710                                 attr = path.shift();
       
   711                             }
       
   712 
       
   713                             if (path && aggAttrs[attr] && aggAttrs[attr].value) {
       
   714                                 O.setValue(aggAttrs[attr].value, path, val);
       
   715                             } else if (!path){
       
   716                                 if (!aggAttrs[attr]) {
       
   717                                     aggAttrs[attr] = cfg;
       
   718                                 } else {
       
   719                                     Y.mix(aggAttrs[attr], cfg, true, cfgProps);
       
   720                                 }
       
   721                             }
       
   722                         }
       
   723                     }
       
   724                 }
       
   725             }
       
   726 
       
   727             return aggAttrs;
       
   728         },
       
   729 
       
   730         /**
       
   731          * Initializes the class hierarchy for the instance, which includes 
       
   732          * initializing attributes for each class defined in the class's 
       
   733          * static <a href="#property_Base.ATTRS">ATTRS</a> property and 
       
   734          * invoking the initializer method on the prototype of each class in the hierarchy.
       
   735          *
       
   736          * @method _initHierarchy
       
   737          * @param {Object} userVals Object with configuration property name/value pairs
       
   738          * @private
       
   739          */
       
   740         _initHierarchy : function(userVals) {
       
   741             var lazy = this._lazyAddAttrs,
       
   742                 constr,
       
   743                 constrProto,
       
   744                 ci,
       
   745                 ei,
       
   746                 el,
       
   747                 classes = this._getClasses(),
       
   748                 attrCfgs = this._getAttrCfgs();
       
   749 
       
   750             for (ci = classes.length-1; ci >= 0; ci--) {
       
   751 
       
   752                 constr = classes[ci];
       
   753                 constrProto = constr.prototype;
       
   754 
       
   755                 if (constr._yuibuild && constr._yuibuild.exts && !constr._yuibuild.dynamic) {
       
   756                     for (ei = 0, el = constr._yuibuild.exts.length; ei < el; ei++) {
       
   757                         constr._yuibuild.exts[ei].apply(this, arguments);
       
   758                     }
       
   759                 }
       
   760 
       
   761                 this.addAttrs(this._filterAttrCfgs(constr, attrCfgs), userVals, lazy);
       
   762 
       
   763                 if (constrProto.hasOwnProperty(INITIALIZER)) {
       
   764                     constrProto.initializer.apply(this, arguments);
       
   765                 }
       
   766             }
       
   767         },
       
   768 
       
   769         /**
       
   770          * Destroys the class hierarchy for this instance by invoking
       
   771          * the descructor method on the prototype of each class in the hierarchy.
       
   772          *
       
   773          * @method _destroyHierarchy
       
   774          * @private
       
   775          */
       
   776         _destroyHierarchy : function() {
       
   777             var constr,
       
   778                 constrProto,
       
   779                 ci, cl,
       
   780                 classes = this._getClasses();
       
   781 
       
   782             for (ci = 0, cl = classes.length; ci < cl; ci++) {
       
   783                 constr = classes[ci];
       
   784                 constrProto = constr.prototype;
       
   785                 if (constrProto.hasOwnProperty(DESTRUCTOR)) {
       
   786                     constrProto.destructor.apply(this, arguments);
       
   787                 }
       
   788             }
       
   789         },
       
   790 
       
   791         /**
       
   792          * Default toString implementation. Provides the constructor NAME
       
   793          * and the instance ID.
       
   794          *
       
   795          * @method toString
       
   796          * @return {String} String representation for this object
       
   797          */
       
   798         toString: function() {
       
   799             return this.constructor.NAME + "[" + Y.stamp(this) + "]";
       
   800         }
       
   801     };
       
   802 
       
   803     // Straightup augment, no wrapper functions
       
   804     Y.mix(Base, Y.Attribute, false, null, 1);
       
   805     Y.mix(Base, PluginHost, false, null, 1);
       
   806 
       
   807     /**
       
   808      * Alias for <a href="Plugin.Host.html#method_Plugin.Host.plug">Plugin.Host.plug</a>. See aliased 
       
   809      * method for argument and return value details.
       
   810      *
       
   811      * @method Base.plug
       
   812      * @static
       
   813      */
       
   814     Base.plug = PluginHost.plug;
       
   815 
       
   816     /**
       
   817      * Alias for <a href="Plugin.Host.html#method_Plugin.Host.unplug">Plugin.Host.unplug</a>. See the 
       
   818      * aliased method for argument and return value details.
       
   819      *
       
   820      * @method Base.unplug
       
   821      * @static
       
   822      */
       
   823     Base.unplug = PluginHost.unplug;
       
   824 
       
   825     // Fix constructor
       
   826     Base.prototype.constructor = Base;
       
   827 
       
   828     Y.Base = Base;
       
   829 
       
   830 
       
   831 
       
   832 }, '3.0.0b1' ,{requires:['attribute']});
       
   833 
       
   834 YUI.add('base-build', function(Y) {
       
   835 
       
   836     /**
       
   837      * The base-build submodule provides Base.build functionality, which
       
   838      * can be used to create custom classes, by aggregating extensions onto 
       
   839      * a main class.
       
   840      *
       
   841      * @module base
       
   842      * @submodule base-build
       
   843      * @for Base
       
   844      */
       
   845 
       
   846     var Base = Y.Base,
       
   847         L = Y.Lang;
       
   848 
       
   849     /**
       
   850      * The build configuration for the Base class.
       
   851      *
       
   852      * Defines the static fields which need to be aggregated
       
   853      * when the Base class is used as the main class passed to 
       
   854      * the <a href="#method_Base.build">Base.build</a> method.
       
   855      *
       
   856      * @property Base._buildCfg
       
   857      * @type Object
       
   858      * @static
       
   859      * @final
       
   860      * @private
       
   861      */
       
   862     Base._buildCfg = {
       
   863         aggregates : ["ATTRS", "_PLUG", "_UNPLUG"]
       
   864     };
       
   865 
       
   866     /**
       
   867      * <p>
       
   868      * Builds a custom constructor function (class) from the
       
   869      * main function, and array of extension functions (classes)
       
   870      * provided. The NAME field for the constructor function is 
       
   871      * defined by the first argument passed in.
       
   872      * </p>
       
   873      * <p>
       
   874      * The cfg object supports the following properties
       
   875      * </p>
       
   876      * <dl>
       
   877      *    <dt>dynamic &#60;boolean&#62;</dt>
       
   878      *    <dd>
       
   879      *    <p>If true (default), a completely new class
       
   880      *    is created which extends the main class, and acts as the 
       
   881      *    host on which the extension classes are augmented.</p>
       
   882      *    <p>If false, the extensions classes are augmented directly to
       
   883      *    the main class, modifying the main class' prototype.</p>
       
   884      *    </dd>
       
   885      *    <dt>aggregates &#60;String[]&#62;</dt>
       
   886      *    <dd>An array of static property names, which will get aggregated
       
   887      *    on to the built class, in addition to the default properties build 
       
   888      *    will always aggregate as defined by the main class' static _buildCfg
       
   889      *    property.
       
   890      *    </dd>
       
   891      * </dl>
       
   892      *
       
   893      * @method Base.build
       
   894      * @static
       
   895      * @param {Function} name The name of the new class. Used to defined the NAME property for the new class.
       
   896      * @param {Function} main The main class on which to base the built class
       
   897      * @param {Function[]} extensions The set of extension classes which will be
       
   898      * augmented/aggregated to the built class.
       
   899      * @param {Object} cfg Optional. Build configuration for the class (see description).
       
   900      * @return {Function} A custom class, created from the provided main and extension classes
       
   901      */
       
   902     Base.build = function(name, main, extensions, cfg) {
       
   903 
       
   904         var build = Base.build,
       
   905             builtClass = build._getClass(main, cfg),
       
   906             aggregates = build._getAggregates(main, cfg),
       
   907             dynamic = builtClass._yuibuild.dynamic,
       
   908             i, l, val, extClass;
       
   909 
       
   910         // Shallow isolate aggregates
       
   911         if (dynamic) {
       
   912             if (aggregates) {
       
   913                 for (i = 0, l = aggregates.length; i < l; ++i) {
       
   914                     val = aggregates[i];
       
   915                     if (main.hasOwnProperty(val)) {
       
   916                         builtClass[val] = L.isArray(main[val]) ? [] : {};
       
   917                     }
       
   918                 }
       
   919                 Y.aggregate(builtClass, main, true, aggregates);
       
   920             }
       
   921         }
       
   922 
       
   923         // Augment/Aggregate
       
   924         for (i = 0, l = extensions.length; i < l; i++) {
       
   925             extClass = extensions[i];
       
   926 
       
   927             if (aggregates) {
       
   928                 Y.aggregate(builtClass, extClass, true, aggregates);
       
   929             }
       
   930 
       
   931             // Old augment
       
   932             Y.mix(builtClass, extClass, true, null, 1);
       
   933 
       
   934             builtClass._yuibuild.exts.push(extClass);
       
   935         }
       
   936 
       
   937         builtClass.prototype.hasImpl = build._hasImpl;
       
   938 
       
   939         if (dynamic) {
       
   940             builtClass.NAME = name;
       
   941             builtClass.prototype.constructor = builtClass;
       
   942         }
       
   943 
       
   944         return builtClass;
       
   945     };
       
   946 
       
   947     Y.mix(Base.build, {
       
   948 
       
   949         _template: function(main) {
       
   950 
       
   951             function BuiltClass() {
       
   952 
       
   953                 BuiltClass.superclass.constructor.apply(this, arguments);
       
   954 
       
   955                 var f = BuiltClass._yuibuild.exts, 
       
   956                     l = f.length,
       
   957                     i;
       
   958 
       
   959                 for (i = 0; i < l; i++) {
       
   960                     f[i].apply(this, arguments);
       
   961                 }
       
   962 
       
   963                 return this;
       
   964             }
       
   965             Y.extend(BuiltClass, main);
       
   966 
       
   967             return BuiltClass;
       
   968         },
       
   969 
       
   970         _hasImpl : function(extClass) {
       
   971             if (this.constructor._yuibuild) {
       
   972                 var f = this.constructor._yuibuild.exts,
       
   973                     l = f.length,
       
   974                     i;
       
   975 
       
   976                 for (i = 0; i < l; i++) {
       
   977                     if (f[i] === extClass) {
       
   978                         return true;
       
   979                     }
       
   980                 }
       
   981             }
       
   982             return false;
       
   983         },
       
   984 
       
   985         _getClass : function(main, cfg) {
       
   986 
       
   987            var dynamic = (cfg && false === cfg.dynamic) ? false : true,
       
   988                 builtClass = (dynamic) ? Base.build._template(main) : main;
       
   989 
       
   990             builtClass._yuibuild = {
       
   991                 id: null,
       
   992                 exts : [],
       
   993                 dynamic : dynamic
       
   994             };
       
   995 
       
   996             return builtClass;
       
   997         },
       
   998 
       
   999         _getAggregates : function(main, cfg) {
       
  1000             var aggr = [],
       
  1001                 cfgAggr = (cfg && cfg.aggregates),
       
  1002                 c = main,
       
  1003                 classAggr;
       
  1004 
       
  1005             while (c && c.prototype) {
       
  1006                 classAggr = c._buildCfg && c._buildCfg.aggregates;
       
  1007                 if (classAggr) {
       
  1008                     aggr = aggr.concat(classAggr);
       
  1009                 }
       
  1010                 c = c.superclass ? c.superclass.constructor : null;
       
  1011             }
       
  1012 
       
  1013             if (cfgAggr) {
       
  1014                 aggr = aggr.concat(cfgAggr);
       
  1015             }
       
  1016 
       
  1017             return aggr;
       
  1018         }
       
  1019     });
       
  1020 
       
  1021 
       
  1022 
       
  1023 }, '3.0.0b1' ,{requires:['base-base']});
       
  1024 
       
  1025 
       
  1026 
       
  1027 YUI.add('base', function(Y){}, '3.0.0b1' ,{use:['base-base', 'base-build']});
       
  1028