src/cm/media/js/lib/yui/yui3.0.0/build/base/base-base.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.0
       
     6 build: 1549
       
     7 */
       
     8 YUI.add('base-base', function(Y) {
       
     9 
       
    10     /**
       
    11      * The base module provides the Base class, which objects requiring attribute and custom event support can extend. 
       
    12      * The module also provides two ways to reuse code - An augmentable Plugin.Host interface which provides plugin support 
       
    13      * (which is augmented to the Base class) and Base.build which provides a way to 
       
    14      * build custom classes using extensions.
       
    15      *
       
    16      * @module base
       
    17      */
       
    18 
       
    19     /**
       
    20      * The base-base submodule provides the Base class without the Plugin support, provided by Plugin.Host, 
       
    21      * and without the extension support provided by Base.build.
       
    22      *
       
    23      * @module base
       
    24      * @submodule base-base
       
    25      */
       
    26     var O = Y.Object,
       
    27         L = Y.Lang,
       
    28         DOT = ".",
       
    29         DESTROY = "destroy",
       
    30         INIT = "init",
       
    31         INITIALIZED = "initialized",
       
    32         DESTROYED = "destroyed",
       
    33         INITIALIZER = "initializer",
       
    34         OBJECT_CONSTRUCTOR = Object.prototype.constructor,
       
    35         DEEP = "deep",
       
    36         SHALLOW = "shallow",
       
    37         DESTRUCTOR = "destructor",
       
    38 
       
    39         Attribute = Y.Attribute;
       
    40 
       
    41     /**
       
    42      * <p>
       
    43      * A base class which objects requiring attributes and custom event support can 
       
    44      * extend. Base also handles the chaining of initializer and destructor methods across 
       
    45      * the hierarchy as part of object construction and destruction. Additionally, attributes configured 
       
    46      * through the static <a href="#property_Base.ATTRS">ATTRS</a> property for each class 
       
    47      * in the hierarchy will be initialized by Base.
       
    48      * </p>
       
    49      *
       
    50      * <p>
       
    51      * The static <a href="#property_Base.NAME">NAME</a> property of each class extending 
       
    52      * from Base will be used as the identifier for the class, and is used by Base to prefix 
       
    53      * all events fired by instances of that class.
       
    54      * </p>
       
    55      * @class Base
       
    56      * @constructor
       
    57      * @uses Attribute
       
    58      * @uses Plugin.Host
       
    59      *
       
    60      * @param {Object} config Object with configuration property name/value pairs
       
    61      */
       
    62     function Base() {
       
    63 
       
    64         Attribute.call(this);
       
    65 
       
    66         // If Plugin.Host has been augmented [ through base-pluginhost ], setup it's
       
    67         // initial state, but don't initialize Plugins yet. That's done after initialization.
       
    68         var PluginHost = Y.Plugin && Y.Plugin.Host;  
       
    69         if (this._initPlugins && PluginHost) {
       
    70             PluginHost.call(this);
       
    71         }
       
    72 
       
    73         if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
       
    74 
       
    75         this.init.apply(this, arguments);
       
    76     }
       
    77 
       
    78     /**
       
    79      * The list of properties which can be configured for 
       
    80      * each attribute (e.g. setter, getter, writeOnce, readOnly etc.)
       
    81      *
       
    82      * @property Base._ATTR_CFG
       
    83      * @type Array
       
    84      * @static
       
    85      * @private
       
    86      */
       
    87     Base._ATTR_CFG = Attribute._ATTR_CFG.concat("cloneDefaultValue");
       
    88 
       
    89     /**
       
    90      * <p>
       
    91      * The string to be used to identify instances of 
       
    92      * this class, for example in prefixing events.
       
    93      * </p>
       
    94      * <p>
       
    95      * Classes extending Base, should define their own
       
    96      * static NAME property, which should be camelCase by
       
    97      * convention (e.g. MyClass.NAME = "myClass";).
       
    98      * </p>
       
    99      * @property Base.NAME
       
   100      * @type String
       
   101      * @static
       
   102      */
       
   103     Base.NAME = "base";
       
   104 
       
   105     /**
       
   106      * The default set of attributes which will be available for instances of this class, and 
       
   107      * their configuration. In addition to the configuration properties listed by 
       
   108      * Attribute's <a href="Attribute.html#method_addAttr">addAttr</a> method, the attribute 
       
   109      * can also be configured with a "cloneDefaultValue" property, which defines how the statically
       
   110      * defined value field should be protected ("shallow", "deep" and false are supported values). 
       
   111      *
       
   112      * By default if the value is an object literal or an array it will be "shallow" cloned, to 
       
   113      * protect the default value.
       
   114      *
       
   115      * @property Base.ATTRS
       
   116      * @type Object
       
   117      * @static
       
   118      */
       
   119     Base.ATTRS = {
       
   120         /**
       
   121          * Flag indicating whether or not this object
       
   122          * has been through the init lifecycle phase.
       
   123          *
       
   124          * @attribute initialized
       
   125          * @readonly
       
   126          * @default false
       
   127          * @type boolean
       
   128          */
       
   129         initialized: {
       
   130             readOnly:true,
       
   131             value:false
       
   132         },
       
   133 
       
   134         /**
       
   135          * Flag indicating whether or not this object
       
   136          * has been through the destroy lifecycle phase.
       
   137          *
       
   138          * @attribute destroyed
       
   139          * @readonly
       
   140          * @default false
       
   141          * @type boolean
       
   142          */
       
   143         destroyed: {
       
   144             readOnly:true,
       
   145             value:false
       
   146         }
       
   147     };
       
   148 
       
   149     Base.prototype = {
       
   150 
       
   151         /**
       
   152          * Init lifecycle method, invoked during construction.
       
   153          * Fires the init event prior to setting up attributes and 
       
   154          * invoking initializers for the class hierarchy.
       
   155          *
       
   156          * @method init
       
   157          * @final
       
   158          * @chainable
       
   159          * @param {Object} config Object with configuration property name/value pairs
       
   160          * @return {Base} A reference to this object
       
   161          */
       
   162         init: function(config) {
       
   163 
       
   164             /**
       
   165              * The string used to identify the class of this object.
       
   166              *
       
   167              * @deprecated Use this.constructor.NAME
       
   168              * @property name
       
   169              * @type String
       
   170              */
       
   171             this._yuievt.config.prefix = this.name = this.constructor.NAME;
       
   172 
       
   173             /**
       
   174              * <p>
       
   175              * Lifecycle event for the init phase, fired prior to initialization. 
       
   176              * Invoking the preventDefault() method on the event object provided 
       
   177              * to subscribers will prevent initialization from occuring.
       
   178              * </p>
       
   179              * <p>
       
   180              * Subscribers to the "after" momemt of this event, will be notified
       
   181              * after initialization of the object is complete (and therefore
       
   182              * cannot prevent initialization).
       
   183              * </p>
       
   184              *
       
   185              * @event init
       
   186              * @preventable _defInitFn
       
   187              * @param {EventFacade} e Event object, with a cfg property which 
       
   188              * refers to the configuration object passed to the constructor.
       
   189              */
       
   190             this.publish(INIT, {
       
   191                 queuable:false,
       
   192                 defaultFn:this._defInitFn
       
   193             });
       
   194 
       
   195             if (config) {
       
   196                 if (config.on) {
       
   197                     this.on(config.on);
       
   198                 }
       
   199                 if (config.after) {
       
   200                     this.after(config.after);
       
   201                 }
       
   202             }
       
   203 
       
   204             this.fire(INIT, {cfg: config});
       
   205 
       
   206             return this;
       
   207         },
       
   208 
       
   209         /**
       
   210          * <p>
       
   211          * Destroy lifecycle method. Fires the destroy
       
   212          * event, prior to invoking destructors for the
       
   213          * class hierarchy.
       
   214          * </p>
       
   215          * <p>
       
   216          * Subscribers to the destroy
       
   217          * event can invoke preventDefault on the event object, to prevent destruction
       
   218          * from proceeding.
       
   219          * </p>
       
   220          * @method destroy
       
   221          * @return {Base} A reference to this object
       
   222          * @final
       
   223          * @chainable
       
   224          */
       
   225         destroy: function() {
       
   226 
       
   227             /**
       
   228              * <p>
       
   229              * Lifecycle event for the destroy phase, 
       
   230              * fired prior to destruction. Invoking the preventDefault 
       
   231              * method on the event object provided to subscribers will 
       
   232              * prevent destruction from proceeding.
       
   233              * </p>
       
   234              * <p>
       
   235              * Subscribers to the "after" moment of this event, will be notified
       
   236              * after destruction is complete (and as a result cannot prevent
       
   237              * destruction).
       
   238              * </p>
       
   239              * @event destroy
       
   240              * @preventable _defDestroyFn
       
   241              * @param {EventFacade} e Event object
       
   242              */
       
   243             this.publish(DESTROY, {
       
   244                 queuable:false,
       
   245                 defaultFn: this._defDestroyFn
       
   246             });
       
   247             this.fire(DESTROY);
       
   248             return this;
       
   249         },
       
   250 
       
   251         /**
       
   252          * Default init event handler
       
   253          *
       
   254          * @method _defInitFn
       
   255          * @param {EventFacade} e Event object, with a cfg property which 
       
   256          * refers to the configuration object passed to the constructor.
       
   257          * @protected
       
   258          */
       
   259         _defInitFn : function(e) {
       
   260             this._initHierarchy(e.cfg);
       
   261             if (this._initPlugins) {
       
   262                 // Need to initPlugins manually, to handle constructor parsing, static Plug parsing
       
   263                 this._initPlugins(e.cfg);
       
   264             }
       
   265             this._set(INITIALIZED, true);
       
   266         },
       
   267 
       
   268         /**
       
   269          * Default destroy event handler
       
   270          *
       
   271          * @method _defDestroyFn
       
   272          * @param {EventFacade} e Event object
       
   273          * @protected
       
   274          */
       
   275         _defDestroyFn : function(e) {
       
   276             this._destroyHierarchy();
       
   277             if (this._destroyPlugins) {
       
   278                 this._destroyPlugins();
       
   279             }
       
   280             this._set(DESTROYED, true);
       
   281         },
       
   282 
       
   283         /**
       
   284          * Returns the class hierarchy for this object, with Base being the last class in the array.
       
   285          *
       
   286          * @method _getClasses
       
   287          * @protected
       
   288          * @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
       
   289          * This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the 
       
   290          * cached value.
       
   291          */
       
   292         _getClasses : function() {
       
   293             if (!this._classes) {
       
   294                 this._initHierarchyData();
       
   295             }
       
   296             return this._classes;
       
   297         },
       
   298 
       
   299         /**
       
   300          * Returns an aggregated set of attribute configurations, by traversing the class hierarchy.
       
   301          *
       
   302          * @method _getAttrCfgs
       
   303          * @protected
       
   304          * @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
       
   305          * This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
       
   306          * the cached value.
       
   307          */
       
   308         _getAttrCfgs : function() {
       
   309             if (!this._attrs) {
       
   310                 this._initHierarchyData();
       
   311             }
       
   312             return this._attrs;
       
   313         },
       
   314 
       
   315         /**
       
   316          * A helper method used when processing ATTRS across the class hierarchy during 
       
   317          * initialization. Returns a disposable object with the attributes defined for 
       
   318          * the provided class, extracted from the set of all attributes passed in .
       
   319          *
       
   320          * @method _filterAttrCfs
       
   321          * @private
       
   322          *
       
   323          * @param {Function} clazz The class for which the desired attributes are required.
       
   324          * @param {Object} allCfgs The set of all attribute configurations for this instance. 
       
   325          * Attributes will be removed from this set, if they belong to the filtered class, so
       
   326          * that by the time all classes are processed, allCfgs will be empty.
       
   327          * 
       
   328          * @return {Object} The set of attributes belonging to the class passed in, in the form
       
   329          * of an object with attribute name/configuration pairs.
       
   330          */
       
   331         _filterAttrCfgs : function(clazz, allCfgs) {
       
   332             var cfgs = null, attr, attrs = clazz.ATTRS;
       
   333 
       
   334             if (attrs) {
       
   335                 for (attr in attrs) {
       
   336                     if (attrs.hasOwnProperty(attr) && allCfgs[attr]) {
       
   337                         cfgs = cfgs || {};
       
   338                         cfgs[attr] = allCfgs[attr];
       
   339                         delete allCfgs[attr];
       
   340                     }
       
   341                 }
       
   342             }
       
   343 
       
   344             return cfgs;
       
   345         },
       
   346 
       
   347         /**
       
   348          * A helper method used by _getClasses and _getAttrCfgs, which determines both
       
   349          * the array of classes and aggregate set of attribute configurations
       
   350          * across the class hierarchy for the instance.
       
   351          * 
       
   352          * @method _initHierarchyData
       
   353          * @private
       
   354          */
       
   355         _initHierarchyData : function() {
       
   356             var c = this.constructor, 
       
   357                 classes = [],
       
   358                 attrs = [];
       
   359 
       
   360             while (c) {
       
   361                 // Add to classes
       
   362                 classes[classes.length] = c;
       
   363 
       
   364                 // Add to attributes
       
   365                 if (c.ATTRS) {
       
   366                     attrs[attrs.length] = c.ATTRS;
       
   367                 }
       
   368                 c = c.superclass ? c.superclass.constructor : null;
       
   369             }
       
   370 
       
   371             this._classes = classes;
       
   372             this._attrs = this._aggregateAttrs(attrs);
       
   373         },
       
   374 
       
   375         /**
       
   376          * A helper method, used by _initHierarchyData to aggregate 
       
   377          * attribute configuration across the instances class hierarchy.
       
   378          *
       
   379          * The method will potect the attribute configuration value to protect the statically defined 
       
   380          * default value in ATTRS if required (if the value is an object literal, array or the 
       
   381          * attribute configuration has cloneDefaultValue set to shallow or deep).
       
   382          *
       
   383          * @method _aggregateAttrs
       
   384          * @private
       
   385          * @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy 
       
   386          * (subclass first, Base last)
       
   387          * @return {Object} The aggregate set of ATTRS definitions for the instance
       
   388          */
       
   389         _aggregateAttrs : function(allAttrs) {
       
   390             var attr,
       
   391                 attrs,
       
   392                 cfg,
       
   393                 val,
       
   394                 path,
       
   395                 i, 
       
   396                 clone, 
       
   397                 cfgProps = Base._ATTR_CFG,
       
   398                 aggAttrs = {};
       
   399 
       
   400             if (allAttrs) {
       
   401                 for (i = allAttrs.length-1; i >= 0; --i) {
       
   402                     attrs = allAttrs[i];
       
   403 
       
   404                     for (attr in attrs) {
       
   405                         if (attrs.hasOwnProperty(attr)) {
       
   406 
       
   407                             // Protect config passed in
       
   408                             cfg = Y.mix({}, attrs[attr], true, cfgProps);
       
   409 
       
   410                             val = cfg.value;
       
   411                             clone = cfg.cloneDefaultValue;
       
   412 
       
   413                             if (val) {
       
   414                                 if ( (clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val))) || clone === DEEP || clone === true) {
       
   415                                     cfg.value = Y.clone(val);
       
   416                                 } else if (clone === SHALLOW) {
       
   417                                     cfg.value = Y.merge(val);
       
   418                                 }
       
   419                                 // else if (clone === false), don't clone the static default value. 
       
   420                                 // It's intended to be used by reference.
       
   421                             }
       
   422 
       
   423                             path = null;
       
   424                             if (attr.indexOf(DOT) !== -1) {
       
   425                                 path = attr.split(DOT);
       
   426                                 attr = path.shift();
       
   427                             }
       
   428 
       
   429                             if (path && aggAttrs[attr] && aggAttrs[attr].value) {
       
   430                                 O.setValue(aggAttrs[attr].value, path, val);
       
   431                             } else if (!path){
       
   432                                 if (!aggAttrs[attr]) {
       
   433                                     aggAttrs[attr] = cfg;
       
   434                                 } else {
       
   435                                     Y.mix(aggAttrs[attr], cfg, true, cfgProps);
       
   436                                 }
       
   437                             }
       
   438                         }
       
   439                     }
       
   440                 }
       
   441             }
       
   442 
       
   443             return aggAttrs;
       
   444         },
       
   445 
       
   446         /**
       
   447          * Initializes the class hierarchy for the instance, which includes 
       
   448          * initializing attributes for each class defined in the class's 
       
   449          * static <a href="#property_Base.ATTRS">ATTRS</a> property and 
       
   450          * invoking the initializer method on the prototype of each class in the hierarchy.
       
   451          *
       
   452          * @method _initHierarchy
       
   453          * @param {Object} userVals Object with configuration property name/value pairs
       
   454          * @private
       
   455          */
       
   456         _initHierarchy : function(userVals) {
       
   457             var lazy = this._lazyAddAttrs,
       
   458                 constr,
       
   459                 constrProto,
       
   460                 ci,
       
   461                 ei,
       
   462                 el,
       
   463                 classes = this._getClasses(),
       
   464                 attrCfgs = this._getAttrCfgs();
       
   465 
       
   466             for (ci = classes.length-1; ci >= 0; ci--) {
       
   467 
       
   468                 constr = classes[ci];
       
   469                 constrProto = constr.prototype;
       
   470 
       
   471                 if (constr._yuibuild && constr._yuibuild.exts && !constr._yuibuild.dynamic) {
       
   472                     for (ei = 0, el = constr._yuibuild.exts.length; ei < el; ei++) {
       
   473                         constr._yuibuild.exts[ei].apply(this, arguments);
       
   474                     }
       
   475                 }
       
   476 
       
   477                 this.addAttrs(this._filterAttrCfgs(constr, attrCfgs), userVals, lazy);
       
   478 
       
   479                 if (constrProto.hasOwnProperty(INITIALIZER)) {
       
   480                     constrProto.initializer.apply(this, arguments);
       
   481                 }
       
   482             }
       
   483         },
       
   484 
       
   485         /**
       
   486          * Destroys the class hierarchy for this instance by invoking
       
   487          * the descructor method on the prototype of each class in the hierarchy.
       
   488          *
       
   489          * @method _destroyHierarchy
       
   490          * @private
       
   491          */
       
   492         _destroyHierarchy : function() {
       
   493             var constr,
       
   494                 constrProto,
       
   495                 ci, cl,
       
   496                 classes = this._getClasses();
       
   497 
       
   498             for (ci = 0, cl = classes.length; ci < cl; ci++) {
       
   499                 constr = classes[ci];
       
   500                 constrProto = constr.prototype;
       
   501                 if (constrProto.hasOwnProperty(DESTRUCTOR)) {
       
   502                     constrProto.destructor.apply(this, arguments);
       
   503                 }
       
   504             }
       
   505         },
       
   506 
       
   507         /**
       
   508          * Default toString implementation. Provides the constructor NAME
       
   509          * and the instance ID.
       
   510          *
       
   511          * @method toString
       
   512          * @return {String} String representation for this object
       
   513          */
       
   514         toString: function() {
       
   515             return this.constructor.NAME + "[" + Y.stamp(this) + "]";
       
   516         }
       
   517     };
       
   518 
       
   519     // Straightup augment, no wrapper functions
       
   520     Y.mix(Base, Attribute, false, null, 1);
       
   521 
       
   522     // Fix constructor
       
   523     Base.prototype.constructor = Base;
       
   524 
       
   525     Y.Base = Base;
       
   526 
       
   527     // Fix constructor
       
   528     Base.prototype.constructor = Base;
       
   529 
       
   530 
       
   531 }, '3.0.0' ,{requires:['attribute-base']});