| 1 | efrain | 1 | YUI.add('attribute-core', function (Y, NAME) {
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 |     /**
 | 
        
           |  |  | 4 |      * The State class maintains state for a collection of named items, with
 | 
        
           |  |  | 5 |      * a varying number of properties defined.
 | 
        
           |  |  | 6 |      *
 | 
        
           |  |  | 7 |      * It avoids the need to create a separate class for the item, and separate instances
 | 
        
           |  |  | 8 |      * of these classes for each item, by storing the state in a 2 level hash table,
 | 
        
           |  |  | 9 |      * improving performance when the number of items is likely to be large.
 | 
        
           |  |  | 10 |      *
 | 
        
           |  |  | 11 |      * @constructor
 | 
        
           |  |  | 12 |      * @class State
 | 
        
           |  |  | 13 |      */
 | 
        
           |  |  | 14 |     Y.State = function() {
 | 
        
           |  |  | 15 |         /**
 | 
        
           |  |  | 16 |          * Hash of attributes
 | 
        
           |  |  | 17 |          * @property data
 | 
        
           |  |  | 18 |          */
 | 
        
           |  |  | 19 |         this.data = {};
 | 
        
           |  |  | 20 |     };
 | 
        
           |  |  | 21 |   | 
        
           |  |  | 22 |     Y.State.prototype = {
 | 
        
           |  |  | 23 |   | 
        
           |  |  | 24 |         /**
 | 
        
           |  |  | 25 |          * Adds a property to an item.
 | 
        
           |  |  | 26 |          *
 | 
        
           |  |  | 27 |          * @method add
 | 
        
           |  |  | 28 |          * @param name {String} The name of the item.
 | 
        
           |  |  | 29 |          * @param key {String} The name of the property.
 | 
        
           |  |  | 30 |          * @param val {Any} The value of the property.
 | 
        
           |  |  | 31 |          */
 | 
        
           |  |  | 32 |         add: function(name, key, val) {
 | 
        
           |  |  | 33 |             var item = this.data[name];
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 |             if (!item) {
 | 
        
           |  |  | 36 |                 item = this.data[name] = {};
 | 
        
           |  |  | 37 |             }
 | 
        
           |  |  | 38 |   | 
        
           |  |  | 39 |             item[key] = val;
 | 
        
           |  |  | 40 |         },
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 |         /**
 | 
        
           |  |  | 43 |          * Adds multiple properties to an item.
 | 
        
           |  |  | 44 |          *
 | 
        
           |  |  | 45 |          * @method addAll
 | 
        
           |  |  | 46 |          * @param name {String} The name of the item.
 | 
        
           |  |  | 47 |          * @param obj {Object} A hash of property/value pairs.
 | 
        
           |  |  | 48 |          */
 | 
        
           |  |  | 49 |         addAll: function(name, obj) {
 | 
        
           |  |  | 50 |             var item = this.data[name],
 | 
        
           |  |  | 51 |                 key;
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 |             if (!item) {
 | 
        
           |  |  | 54 |                 item = this.data[name] = {};
 | 
        
           |  |  | 55 |             }
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 |             for (key in obj) {
 | 
        
           |  |  | 58 |                 if (obj.hasOwnProperty(key)) {
 | 
        
           |  |  | 59 |                     item[key] = obj[key];
 | 
        
           |  |  | 60 |                 }
 | 
        
           |  |  | 61 |             }
 | 
        
           |  |  | 62 |         },
 | 
        
           |  |  | 63 |   | 
        
           |  |  | 64 |         /**
 | 
        
           |  |  | 65 |          * Removes a property from an item.
 | 
        
           |  |  | 66 |          *
 | 
        
           |  |  | 67 |          * @method remove
 | 
        
           |  |  | 68 |          * @param name {String} The name of the item.
 | 
        
           |  |  | 69 |          * @param key {String} The property to remove.
 | 
        
           |  |  | 70 |          */
 | 
        
           |  |  | 71 |         remove: function(name, key) {
 | 
        
           |  |  | 72 |             var item = this.data[name];
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |             if (item) {
 | 
        
           |  |  | 75 |                 delete item[key];
 | 
        
           |  |  | 76 |             }
 | 
        
           |  |  | 77 |         },
 | 
        
           |  |  | 78 |   | 
        
           |  |  | 79 |         /**
 | 
        
           |  |  | 80 |          * Removes multiple properties from an item, or removes the item completely.
 | 
        
           |  |  | 81 |          *
 | 
        
           |  |  | 82 |          * @method removeAll
 | 
        
           |  |  | 83 |          * @param name {String} The name of the item.
 | 
        
           |  |  | 84 |          * @param obj {Object|Array} Collection of properties to delete. If not provided, the entire item is removed.
 | 
        
           |  |  | 85 |          */
 | 
        
           |  |  | 86 |         removeAll: function(name, obj) {
 | 
        
           |  |  | 87 |             var data;
 | 
        
           |  |  | 88 |   | 
        
           |  |  | 89 |             if (!obj) {
 | 
        
           |  |  | 90 |                 data = this.data;
 | 
        
           |  |  | 91 |   | 
        
           |  |  | 92 |                 if (name in data) {
 | 
        
           |  |  | 93 |                     delete data[name];
 | 
        
           |  |  | 94 |                 }
 | 
        
           |  |  | 95 |             } else {
 | 
        
           |  |  | 96 |                 Y.each(obj, function(value, key) {
 | 
        
           |  |  | 97 |                     this.remove(name, typeof key === 'string' ? key : value);
 | 
        
           |  |  | 98 |                 }, this);
 | 
        
           |  |  | 99 |             }
 | 
        
           |  |  | 100 |         },
 | 
        
           |  |  | 101 |   | 
        
           |  |  | 102 |         /**
 | 
        
           |  |  | 103 |          * For a given item, returns the value of the property requested, or undefined if not found.
 | 
        
           |  |  | 104 |          *
 | 
        
           |  |  | 105 |          * @method get
 | 
        
           |  |  | 106 |          * @param name {String} The name of the item
 | 
        
           |  |  | 107 |          * @param key {String} Optional. The property value to retrieve.
 | 
        
           |  |  | 108 |          * @return {Any} The value of the supplied property.
 | 
        
           |  |  | 109 |          */
 | 
        
           |  |  | 110 |         get: function(name, key) {
 | 
        
           |  |  | 111 |             var item = this.data[name];
 | 
        
           |  |  | 112 |   | 
        
           |  |  | 113 |             if (item) {
 | 
        
           |  |  | 114 |                 return item[key];
 | 
        
           |  |  | 115 |             }
 | 
        
           |  |  | 116 |         },
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 |         /**
 | 
        
           |  |  | 119 |          * For the given item, returns an object with all of the
 | 
        
           |  |  | 120 |          * item's property/value pairs. By default the object returned
 | 
        
           |  |  | 121 |          * is a shallow copy of the stored data, but passing in true
 | 
        
           |  |  | 122 |          * as the second parameter will return a reference to the stored
 | 
        
           |  |  | 123 |          * data.
 | 
        
           |  |  | 124 |          *
 | 
        
           |  |  | 125 |          * @method getAll
 | 
        
           |  |  | 126 |          * @param name {String} The name of the item
 | 
        
           |  |  | 127 |          * @param reference {boolean} true, if you want a reference to the stored
 | 
        
           |  |  | 128 |          * object
 | 
        
           |  |  | 129 |          * @return {Object} An object with property/value pairs for the item.
 | 
        
           |  |  | 130 |          */
 | 
        
           |  |  | 131 |         getAll : function(name, reference) {
 | 
        
           |  |  | 132 |             var item = this.data[name],
 | 
        
           |  |  | 133 |                 key, obj;
 | 
        
           |  |  | 134 |   | 
        
           |  |  | 135 |             if (reference) {
 | 
        
           |  |  | 136 |                 obj = item;
 | 
        
           |  |  | 137 |             } else if (item) {
 | 
        
           |  |  | 138 |                 obj = {};
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 |                 for (key in item) {
 | 
        
           |  |  | 141 |                     if (item.hasOwnProperty(key)) {
 | 
        
           |  |  | 142 |                         obj[key] = item[key];
 | 
        
           |  |  | 143 |                     }
 | 
        
           |  |  | 144 |                 }
 | 
        
           |  |  | 145 |             }
 | 
        
           |  |  | 146 |   | 
        
           |  |  | 147 |             return obj;
 | 
        
           |  |  | 148 |         }
 | 
        
           |  |  | 149 |     };
 | 
        
           |  |  | 150 |     /*For log lines*/
 | 
        
           |  |  | 151 |     /*jshint maxlen:200*/
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 |     /**
 | 
        
           |  |  | 154 |      * The attribute module provides an augmentable Attribute implementation, which
 | 
        
           |  |  | 155 |      * adds configurable attributes and attribute change events to the class being
 | 
        
           |  |  | 156 |      * augmented. It also provides a State class, which is used internally by Attribute,
 | 
        
           |  |  | 157 |      * but can also be used independently to provide a name/property/value data structure to
 | 
        
           |  |  | 158 |      * store state.
 | 
        
           |  |  | 159 |      *
 | 
        
           |  |  | 160 |      * @module attribute
 | 
        
           |  |  | 161 |      */
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 |     /**
 | 
        
           |  |  | 164 |      * The attribute-core submodule provides the lightest level of attribute handling support
 | 
        
           |  |  | 165 |      * without Attribute change events, or lesser used methods such as reset(), modifyAttrs(),
 | 
        
           |  |  | 166 |      * and removeAttr().
 | 
        
           |  |  | 167 |      *
 | 
        
           |  |  | 168 |      * @module attribute
 | 
        
           |  |  | 169 |      * @submodule attribute-core
 | 
        
           |  |  | 170 |      */
 | 
        
           |  |  | 171 |     var O = Y.Object,
 | 
        
           |  |  | 172 |         Lang = Y.Lang,
 | 
        
           |  |  | 173 |   | 
        
           |  |  | 174 |         DOT = ".",
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |         // Externally configurable props
 | 
        
           |  |  | 177 |         GETTER = "getter",
 | 
        
           |  |  | 178 |         SETTER = "setter",
 | 
        
           |  |  | 179 |         READ_ONLY = "readOnly",
 | 
        
           |  |  | 180 |         WRITE_ONCE = "writeOnce",
 | 
        
           |  |  | 181 |         INIT_ONLY = "initOnly",
 | 
        
           |  |  | 182 |         VALIDATOR = "validator",
 | 
        
           |  |  | 183 |         VALUE = "value",
 | 
        
           |  |  | 184 |         VALUE_FN = "valueFn",
 | 
        
           |  |  | 185 |         LAZY_ADD = "lazyAdd",
 | 
        
           |  |  | 186 |   | 
        
           |  |  | 187 |         // Used for internal state management
 | 
        
           |  |  | 188 |         ADDED = "added",
 | 
        
           |  |  | 189 |         BYPASS_PROXY = "_bypassProxy",
 | 
        
           |  |  | 190 |         INIT_VALUE = "initValue",
 | 
        
           |  |  | 191 |         LAZY = "lazy",
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |         INVALID_VALUE;
 | 
        
           |  |  | 194 |   | 
        
           |  |  | 195 |     /**
 | 
        
           |  |  | 196 |      * <p>
 | 
        
           |  |  | 197 |      * AttributeCore provides the lightest level of configurable attribute support. It is designed to be
 | 
        
           |  |  | 198 |      * augmented on to a host class, and provides the host with the ability to configure
 | 
        
           |  |  | 199 |      * attributes to store and retrieve state, <strong>but without support for attribute change events</strong>.
 | 
        
           |  |  | 200 |      * </p>
 | 
        
           |  |  | 201 |      * <p>For example, attributes added to the host can be configured:</p>
 | 
        
           |  |  | 202 |      * <ul>
 | 
        
           |  |  | 203 |      *     <li>As read only.</li>
 | 
        
           |  |  | 204 |      *     <li>As write once.</li>
 | 
        
           |  |  | 205 |      *     <li>With a setter function, which can be used to manipulate
 | 
        
           |  |  | 206 |      *     values passed to Attribute's <a href="#method_set">set</a> method, before they are stored.</li>
 | 
        
           |  |  | 207 |      *     <li>With a getter function, which can be used to manipulate stored values,
 | 
        
           |  |  | 208 |      *     before they are returned by Attribute's <a href="#method_get">get</a> method.</li>
 | 
        
           |  |  | 209 |      *     <li>With a validator function, to validate values before they are stored.</li>
 | 
        
           |  |  | 210 |      * </ul>
 | 
        
           |  |  | 211 |      *
 | 
        
           |  |  | 212 |      * <p>See the <a href="#method_addAttr">addAttr</a> method, for the complete set of configuration
 | 
        
           |  |  | 213 |      * options available for attributes.</p>
 | 
        
           |  |  | 214 |      *
 | 
        
           |  |  | 215 |      * <p>Object/Classes based on AttributeCore can augment <a href="AttributeObservable.html">AttributeObservable</a>
 | 
        
           |  |  | 216 |      * (with true for overwrite) and <a href="AttributeExtras.html">AttributeExtras</a> to add attribute event and
 | 
        
           |  |  | 217 |      * additional, less commonly used attribute methods, such as `modifyAttr`, `removeAttr` and `reset`.</p>
 | 
        
           |  |  | 218 |      *
 | 
        
           |  |  | 219 |      * @class AttributeCore
 | 
        
           |  |  | 220 |      * @param attrs {Object} The attributes to add during construction (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 221 |      *        These can also be defined on the constructor being augmented with Attribute by defining the ATTRS property on the constructor.
 | 
        
           |  |  | 222 |      * @param values {Object} The initial attribute values to apply (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 223 |      *        These are not merged/cloned. The caller is responsible for isolating user provided values if required.
 | 
        
           |  |  | 224 |      * @param lazy {boolean} Whether or not to add attributes lazily (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 225 |      */
 | 
        
           |  |  | 226 |     function AttributeCore(attrs, values, lazy) {
 | 
        
           |  |  | 227 |         // HACK: Fix #2531929
 | 
        
           |  |  | 228 |         // Complete hack, to make sure the first clone of a node value in IE doesn't doesn't hurt state - maintains 3.4.1 behavior.
 | 
        
           |  |  | 229 |         // Too late in the release cycle to do anything about the core problem.
 | 
        
           |  |  | 230 |         // The root issue is that cloning a Y.Node instance results in an object which barfs in IE, when you access it's properties (since 3.3.0).
 | 
        
           |  |  | 231 |         this._yuievt = null;
 | 
        
           |  |  | 232 |   | 
        
           |  |  | 233 |         this._initAttrHost(attrs, values, lazy);
 | 
        
           |  |  | 234 |     }
 | 
        
           |  |  | 235 |   | 
        
           |  |  | 236 |     /**
 | 
        
           |  |  | 237 |      * <p>The value to return from an attribute setter in order to prevent the set from going through.</p>
 | 
        
           |  |  | 238 |      *
 | 
        
           |  |  | 239 |      * <p>You can return this value from your setter if you wish to combine validator and setter
 | 
        
           |  |  | 240 |      * functionality into a single setter function, which either returns the massaged value to be stored or
 | 
        
           |  |  | 241 |      * AttributeCore.INVALID_VALUE to prevent invalid values from being stored.</p>
 | 
        
           |  |  | 242 |      *
 | 
        
           |  |  | 243 |      * @property INVALID_VALUE
 | 
        
           |  |  | 244 |      * @type Object
 | 
        
           |  |  | 245 |      * @static
 | 
        
           |  |  | 246 |      * @final
 | 
        
           |  |  | 247 |      */
 | 
        
           |  |  | 248 |     AttributeCore.INVALID_VALUE = {};
 | 
        
           |  |  | 249 |     INVALID_VALUE = AttributeCore.INVALID_VALUE;
 | 
        
           |  |  | 250 |   | 
        
           |  |  | 251 |     /**
 | 
        
           |  |  | 252 |      * The list of properties which can be configured for
 | 
        
           |  |  | 253 |      * each attribute (e.g. setter, getter, writeOnce etc.).
 | 
        
           |  |  | 254 |      *
 | 
        
           |  |  | 255 |      * This property is used internally as a whitelist for faster
 | 
        
           |  |  | 256 |      * Y.mix operations.
 | 
        
           |  |  | 257 |      *
 | 
        
           |  |  | 258 |      * @property _ATTR_CFG
 | 
        
           |  |  | 259 |      * @type Array
 | 
        
           |  |  | 260 |      * @static
 | 
        
           |  |  | 261 |      * @protected
 | 
        
           |  |  | 262 |      */
 | 
        
           |  |  | 263 |     AttributeCore._ATTR_CFG = [SETTER, GETTER, VALIDATOR, VALUE, VALUE_FN, WRITE_ONCE, READ_ONLY, LAZY_ADD, BYPASS_PROXY];
 | 
        
           |  |  | 264 |   | 
        
           |  |  | 265 |     /**
 | 
        
           |  |  | 266 |      * Utility method to protect an attribute configuration hash, by merging the
 | 
        
           |  |  | 267 |      * entire object and the individual attr config objects.
 | 
        
           |  |  | 268 |      *
 | 
        
           |  |  | 269 |      * @method protectAttrs
 | 
        
           |  |  | 270 |      * @static
 | 
        
           |  |  | 271 |      * @param {Object} attrs A hash of attribute to configuration object pairs.
 | 
        
           |  |  | 272 |      * @return {Object} A protected version of the `attrs` argument.
 | 
        
           |  |  | 273 |      */
 | 
        
           |  |  | 274 |     AttributeCore.protectAttrs = function (attrs) {
 | 
        
           |  |  | 275 |         if (attrs) {
 | 
        
           |  |  | 276 |             attrs = Y.merge(attrs);
 | 
        
           |  |  | 277 |             for (var attr in attrs) {
 | 
        
           |  |  | 278 |                 if (attrs.hasOwnProperty(attr)) {
 | 
        
           |  |  | 279 |                     attrs[attr] = Y.merge(attrs[attr]);
 | 
        
           |  |  | 280 |                 }
 | 
        
           |  |  | 281 |             }
 | 
        
           |  |  | 282 |         }
 | 
        
           |  |  | 283 |   | 
        
           |  |  | 284 |         return attrs;
 | 
        
           |  |  | 285 |     };
 | 
        
           |  |  | 286 |   | 
        
           |  |  | 287 |     AttributeCore.prototype = {
 | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 |         /**
 | 
        
           |  |  | 290 |          * Constructor logic for attributes. Initializes the host state, and sets up the inital attributes passed to the
 | 
        
           |  |  | 291 |          * constructor.
 | 
        
           |  |  | 292 |          *
 | 
        
           |  |  | 293 |          * @method _initAttrHost
 | 
        
           |  |  | 294 |          * @param attrs {Object} The attributes to add during construction (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 295 |          *        These can also be defined on the constructor being augmented with Attribute by defining the ATTRS property on the constructor.
 | 
        
           |  |  | 296 |          * @param values {Object} The initial attribute values to apply (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 297 |          *        These are not merged/cloned. The caller is responsible for isolating user provided values if required.
 | 
        
           |  |  | 298 |          * @param lazy {boolean} Whether or not to add attributes lazily (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 299 |          * @private
 | 
        
           |  |  | 300 |          */
 | 
        
           |  |  | 301 |         _initAttrHost : function(attrs, values, lazy) {
 | 
        
           |  |  | 302 |             this._state = new Y.State();
 | 
        
           |  |  | 303 |             this._initAttrs(attrs, values, lazy);
 | 
        
           |  |  | 304 |         },
 | 
        
           |  |  | 305 |   | 
        
           |  |  | 306 |         /**
 | 
        
           |  |  | 307 |          * <p>
 | 
        
           |  |  | 308 |          * Adds an attribute with the provided configuration to the host object.
 | 
        
           |  |  | 309 |          * </p>
 | 
        
           |  |  | 310 |          * <p>
 | 
        
           |  |  | 311 |          * The config argument object supports the following properties:
 | 
        
           |  |  | 312 |          * </p>
 | 
        
           |  |  | 313 |          *
 | 
        
           |  |  | 314 |          * <dl>
 | 
        
           |  |  | 315 |          *    <dt>value <Any></dt>
 | 
        
           |  |  | 316 |          *    <dd>The initial value to set on the attribute</dd>
 | 
        
           |  |  | 317 |          *
 | 
        
           |  |  | 318 |          *    <dt>valueFn <Function | String></dt>
 | 
        
           |  |  | 319 |          *    <dd>
 | 
        
           |  |  | 320 |          *    <p>A function, which will return the initial value to set on the attribute. This is useful
 | 
        
           |  |  | 321 |          *    for cases where the attribute configuration is defined statically, but needs to
 | 
        
           |  |  | 322 |          *    reference the host instance ("this") to obtain an initial value. If both the value and valueFn properties are defined,
 | 
        
           |  |  | 323 |          *    the value returned by the valueFn has precedence over the value property, unless it returns undefined, in which
 | 
        
           |  |  | 324 |          *    case the value property is used.</p>
 | 
        
           |  |  | 325 |          *
 | 
        
           |  |  | 326 |          *    <p>valueFn can also be set to a string, representing the name of the instance method to be used to retrieve the value.</p>
 | 
        
           |  |  | 327 |          *    </dd>
 | 
        
           |  |  | 328 |          *
 | 
        
           |  |  | 329 |          *    <dt>readOnly <boolean></dt>
 | 
        
           |  |  | 330 |          *    <dd>Whether or not the attribute is read only. Attributes having readOnly set to true
 | 
        
           |  |  | 331 |          *        cannot be modified by invoking the set method.</dd>
 | 
        
           |  |  | 332 |          *
 | 
        
           |  |  | 333 |          *    <dt>writeOnce <boolean> or <string></dt>
 | 
        
           |  |  | 334 |          *    <dd>
 | 
        
           |  |  | 335 |          *        Whether or not the attribute is "write once". Attributes having writeOnce set to true,
 | 
        
           |  |  | 336 |          *        can only have their values set once, be it through the default configuration,
 | 
        
           |  |  | 337 |          *        constructor configuration arguments, or by invoking set.
 | 
        
           |  |  | 338 |          *        <p>The writeOnce attribute can also be set to the string "initOnly",
 | 
        
           |  |  | 339 |          *         in which case the attribute can only be set during initialization
 | 
        
           |  |  | 340 |          *        (when used with Base, this means it can only be set during construction)</p>
 | 
        
           |  |  | 341 |          *    </dd>
 | 
        
           |  |  | 342 |          *
 | 
        
           |  |  | 343 |          *    <dt>setter <Function | String></dt>
 | 
        
           |  |  | 344 |          *    <dd>
 | 
        
           |  |  | 345 |          *    <p>The setter function used to massage or normalize the value passed to the set method for the attribute.
 | 
        
           |  |  | 346 |          *    The value returned by the setter will be the final stored value. Returning
 | 
        
           |  |  | 347 |          *    <a href="#property_Attribute.INVALID_VALUE">Attribute.INVALID_VALUE</a>, from the setter will prevent
 | 
        
           |  |  | 348 |          *    the value from being stored.
 | 
        
           |  |  | 349 |          *    </p>
 | 
        
           |  |  | 350 |          *
 | 
        
           |  |  | 351 |          *    <p>setter can also be set to a string, representing the name of the instance method to be used as the setter function.</p>
 | 
        
           |  |  | 352 |          *    </dd>
 | 
        
           |  |  | 353 |          *
 | 
        
           |  |  | 354 |          *    <dt>getter <Function | String></dt>
 | 
        
           |  |  | 355 |          *    <dd>
 | 
        
           |  |  | 356 |          *    <p>
 | 
        
           |  |  | 357 |          *    The getter function used to massage or normalize the value returned by the get method for the attribute.
 | 
        
           |  |  | 358 |          *    The value returned by the getter function is the value which will be returned to the user when they
 | 
        
           |  |  | 359 |          *    invoke get.
 | 
        
           |  |  | 360 |          *    </p>
 | 
        
           |  |  | 361 |          *
 | 
        
           |  |  | 362 |          *    <p>getter can also be set to a string, representing the name of the instance method to be used as the getter function.</p>
 | 
        
           |  |  | 363 |          *    </dd>
 | 
        
           |  |  | 364 |          *
 | 
        
           |  |  | 365 |          *    <dt>validator <Function | String></dt>
 | 
        
           |  |  | 366 |          *    <dd>
 | 
        
           |  |  | 367 |          *    <p>
 | 
        
           |  |  | 368 |          *    The validator function invoked prior to setting the stored value. Returning
 | 
        
           |  |  | 369 |          *    false from the validator function will prevent the value from being stored.
 | 
        
           |  |  | 370 |          *    </p>
 | 
        
           |  |  | 371 |          *
 | 
        
           |  |  | 372 |          *    <p>validator can also be set to a string, representing the name of the instance method to be used as the validator function.</p>
 | 
        
           |  |  | 373 |          *    </dd>
 | 
        
           |  |  | 374 |          *
 | 
        
           |  |  | 375 |          *    <dt>lazyAdd <boolean></dt>
 | 
        
           |  |  | 376 |          *    <dd>Whether or not to delay initialization of the attribute until the first call to get/set it.
 | 
        
           |  |  | 377 |          *    This flag can be used to over-ride lazy initialization on a per attribute basis, when adding multiple attributes through
 | 
        
           |  |  | 378 |          *    the <a href="#method_addAttrs">addAttrs</a> method.</dd>
 | 
        
           |  |  | 379 |          *
 | 
        
           |  |  | 380 |          * </dl>
 | 
        
           |  |  | 381 |          *
 | 
        
           |  |  | 382 |          * <p>The setter, getter and validator are invoked with the value and name passed in as the first and second arguments, and with
 | 
        
           |  |  | 383 |          * the context ("this") set to the host object.</p>
 | 
        
           |  |  | 384 |          *
 | 
        
           |  |  | 385 |          * <p>Configuration properties outside of the list mentioned above are considered private properties used internally by attribute,
 | 
        
           |  |  | 386 |          * and are not intended for public use.</p>
 | 
        
           |  |  | 387 |          *
 | 
        
           |  |  | 388 |          * @method addAttr
 | 
        
           |  |  | 389 |          *
 | 
        
           |  |  | 390 |          * @param {String} name The name of the attribute.
 | 
        
           |  |  | 391 |          * @param {Object} config An object with attribute configuration property/value pairs, specifying the configuration for the attribute.
 | 
        
           |  |  | 392 |          *
 | 
        
           |  |  | 393 |          * <p>
 | 
        
           |  |  | 394 |          * <strong>NOTE:</strong> The configuration object is modified when adding an attribute, so if you need
 | 
        
           |  |  | 395 |          * to protect the original values, you will need to merge the object.
 | 
        
           |  |  | 396 |          * </p>
 | 
        
           |  |  | 397 |          *
 | 
        
           |  |  | 398 |          * @param {boolean} lazy (optional) Whether or not to add this attribute lazily (on the first call to get/set).
 | 
        
           |  |  | 399 |          *
 | 
        
           |  |  | 400 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 401 |          *
 | 
        
           |  |  | 402 |          * @chainable
 | 
        
           |  |  | 403 |          */
 | 
        
           |  |  | 404 |         addAttr : function(name, config, lazy) {
 | 
        
           |  |  | 405 |   | 
        
           |  |  | 406 |             Y.log('Adding attribute: ' + name, 'info', 'attribute');
 | 
        
           |  |  | 407 |   | 
        
           |  |  | 408 |             var host = this, // help compression
 | 
        
           |  |  | 409 |                 state = host._state,
 | 
        
           |  |  | 410 |                 data = state.data,
 | 
        
           |  |  | 411 |                 value,
 | 
        
           |  |  | 412 |                 added,
 | 
        
           |  |  | 413 |                 hasValue;
 | 
        
           |  |  | 414 |   | 
        
           |  |  | 415 |             config = config || {};
 | 
        
           |  |  | 416 |   | 
        
           |  |  | 417 |             if (LAZY_ADD in config) {
 | 
        
           |  |  | 418 |                 lazy = config[LAZY_ADD];
 | 
        
           |  |  | 419 |             }
 | 
        
           |  |  | 420 |   | 
        
           |  |  | 421 |             added = state.get(name, ADDED);
 | 
        
           |  |  | 422 |   | 
        
           |  |  | 423 |             if (lazy && !added) {
 | 
        
           |  |  | 424 |                 state.data[name] = {
 | 
        
           |  |  | 425 |                     lazy : config,
 | 
        
           |  |  | 426 |                     added : true
 | 
        
           |  |  | 427 |                 };
 | 
        
           |  |  | 428 |             } else {
 | 
        
           |  |  | 429 |   | 
        
           |  |  | 430 |                 if (added && !config.isLazyAdd) { Y.log('Attribute: ' + name + ' already exists. Cannot add it again without removing it first', 'warn', 'attribute'); }
 | 
        
           |  |  | 431 |   | 
        
           |  |  | 432 |                 if (!added || config.isLazyAdd) {
 | 
        
           |  |  | 433 |   | 
        
           |  |  | 434 |                     hasValue = (VALUE in config);
 | 
        
           |  |  | 435 |   | 
        
           |  |  | 436 |                     if (config.readOnly && !hasValue) { Y.log('readOnly attribute: ' + name + ', added without an initial value. Value will be set on initial call to set', 'warn', 'attribute');}
 | 
        
           |  |  | 437 |   | 
        
           |  |  | 438 |                     if (hasValue) {
 | 
        
           |  |  | 439 |   | 
        
           |  |  | 440 |                         // We'll go through set, don't want to set value in config directly
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |                         // PERF TODO: VALIDATE: See if setting this to undefined is sufficient. We use to delete before.
 | 
        
           |  |  | 443 |                         // In certain code paths/use cases, undefined may not be the same as not present.
 | 
        
           |  |  | 444 |                         // If not, we can set it to some known fixed value (like INVALID_VALUE, say INITIALIZING_VALUE) for performance,
 | 
        
           |  |  | 445 |                         // to avoid a delete which seems to help a lot.
 | 
        
           |  |  | 446 |   | 
        
           |  |  | 447 |                         value = config.value;
 | 
        
           |  |  | 448 |                         config.value = undefined;
 | 
        
           |  |  | 449 |                     }
 | 
        
           |  |  | 450 |   | 
        
           |  |  | 451 |                     config.added = true;
 | 
        
           |  |  | 452 |                     config.initializing = true;
 | 
        
           |  |  | 453 |   | 
        
           |  |  | 454 |                     data[name] = config;
 | 
        
           |  |  | 455 |   | 
        
           |  |  | 456 |                     if (hasValue) {
 | 
        
           |  |  | 457 |                         // Go through set, so that raw values get normalized/validated
 | 
        
           |  |  | 458 |                         host.set(name, value);
 | 
        
           |  |  | 459 |                     }
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |                     config.initializing = false;
 | 
        
           |  |  | 462 |                 }
 | 
        
           |  |  | 463 |             }
 | 
        
           |  |  | 464 |   | 
        
           |  |  | 465 |             return host;
 | 
        
           |  |  | 466 |         },
 | 
        
           |  |  | 467 |   | 
        
           |  |  | 468 |         /**
 | 
        
           |  |  | 469 |          * Checks if the given attribute has been added to the host
 | 
        
           |  |  | 470 |          *
 | 
        
           |  |  | 471 |          * @method attrAdded
 | 
        
           |  |  | 472 |          * @param {String} name The name of the attribute to check.
 | 
        
           |  |  | 473 |          * @return {boolean} true if an attribute with the given name has been added, false if it hasn't.
 | 
        
           |  |  | 474 |          *         This method will return true for lazily added attributes.
 | 
        
           |  |  | 475 |          */
 | 
        
           |  |  | 476 |         attrAdded: function(name) {
 | 
        
           |  |  | 477 |             return !!(this._state.get(name, ADDED));
 | 
        
           |  |  | 478 |         },
 | 
        
           |  |  | 479 |   | 
        
           |  |  | 480 |         /**
 | 
        
           |  |  | 481 |          * Returns the current value of the attribute. If the attribute
 | 
        
           |  |  | 482 |          * has been configured with a 'getter' function, this method will delegate
 | 
        
           |  |  | 483 |          * to the 'getter' to obtain the value of the attribute.
 | 
        
           |  |  | 484 |          *
 | 
        
           |  |  | 485 |          * @method get
 | 
        
           |  |  | 486 |          *
 | 
        
           |  |  | 487 |          * @param {String} name The name of the attribute. If the value of the attribute is an Object,
 | 
        
           |  |  | 488 |          * dot notation can be used to obtain the value of a property of the object (e.g. <code>get("x.y.z")</code>)
 | 
        
           |  |  | 489 |          *
 | 
        
           |  |  | 490 |          * @return {Any} The value of the attribute
 | 
        
           |  |  | 491 |          */
 | 
        
           |  |  | 492 |         get : function(name) {
 | 
        
           |  |  | 493 |             return this._getAttr(name);
 | 
        
           |  |  | 494 |         },
 | 
        
           |  |  | 495 |   | 
        
           |  |  | 496 |         /**
 | 
        
           |  |  | 497 |          * Checks whether or not the attribute is one which has been
 | 
        
           |  |  | 498 |          * added lazily and still requires initialization.
 | 
        
           |  |  | 499 |          *
 | 
        
           |  |  | 500 |          * @method _isLazyAttr
 | 
        
           |  |  | 501 |          * @private
 | 
        
           |  |  | 502 |          * @param {String} name The name of the attribute
 | 
        
           |  |  | 503 |          * @return {boolean} true if it's a lazily added attribute, false otherwise.
 | 
        
           |  |  | 504 |          */
 | 
        
           |  |  | 505 |         _isLazyAttr: function(name) {
 | 
        
           |  |  | 506 |             return this._state.get(name, LAZY);
 | 
        
           |  |  | 507 |         },
 | 
        
           |  |  | 508 |   | 
        
           |  |  | 509 |         /**
 | 
        
           |  |  | 510 |          * Finishes initializing an attribute which has been lazily added.
 | 
        
           |  |  | 511 |          *
 | 
        
           |  |  | 512 |          * @method _addLazyAttr
 | 
        
           |  |  | 513 |          * @private
 | 
        
           |  |  | 514 |          * @param {Object} name The name of the attribute
 | 
        
           |  |  | 515 |          * @param {Object} [lazyCfg] Optional config hash for the attribute. This is added for performance
 | 
        
           |  |  | 516 |          * along the critical path, where the calling method has already obtained lazy config from state.
 | 
        
           |  |  | 517 |          */
 | 
        
           |  |  | 518 |         _addLazyAttr: function(name, lazyCfg) {
 | 
        
           |  |  | 519 |             var state = this._state;
 | 
        
           |  |  | 520 |   | 
        
           |  |  | 521 |             lazyCfg = lazyCfg || state.get(name, LAZY);
 | 
        
           |  |  | 522 |   | 
        
           |  |  | 523 |             if (lazyCfg) {
 | 
        
           |  |  | 524 |   | 
        
           |  |  | 525 |                 // PERF TODO: For App's id override, otherwise wouldn't be
 | 
        
           |  |  | 526 |                 // needed. It expects to find it in the cfg for it's
 | 
        
           |  |  | 527 |                 // addAttr override. Would like to remove, once App override is
 | 
        
           |  |  | 528 |                 // removed.
 | 
        
           |  |  | 529 |                 state.data[name].lazy = undefined;
 | 
        
           |  |  | 530 |   | 
        
           |  |  | 531 |                 lazyCfg.isLazyAdd = true;
 | 
        
           |  |  | 532 |   | 
        
           |  |  | 533 |                 this.addAttr(name, lazyCfg);
 | 
        
           |  |  | 534 |             }
 | 
        
           |  |  | 535 |         },
 | 
        
           |  |  | 536 |   | 
        
           |  |  | 537 |         /**
 | 
        
           |  |  | 538 |          * Sets the value of an attribute.
 | 
        
           |  |  | 539 |          *
 | 
        
           |  |  | 540 |          * @method set
 | 
        
           |  |  | 541 |          * @chainable
 | 
        
           |  |  | 542 |          *
 | 
        
           |  |  | 543 |          * @param {String} name The name of the attribute. If the
 | 
        
           |  |  | 544 |          * current value of the attribute is an Object, dot notation can be used
 | 
        
           |  |  | 545 |          * to set the value of a property within the object (e.g. <code>set("x.y.z", 5)</code>).
 | 
        
           |  |  | 546 |          * @param {Any} value The value to set the attribute to.
 | 
        
           |  |  | 547 |          * @param {Object} [opts] Optional data providing the circumstances for the change.
 | 
        
           |  |  | 548 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 549 |          */
 | 
        
           |  |  | 550 |         set : function(name, val, opts) {
 | 
        
           |  |  | 551 |             return this._setAttr(name, val, opts);
 | 
        
           |  |  | 552 |         },
 | 
        
           |  |  | 553 |   | 
        
           |  |  | 554 |         /**
 | 
        
           |  |  | 555 |          * Allows setting of readOnly/writeOnce attributes. See <a href="#method_set">set</a> for argument details.
 | 
        
           |  |  | 556 |          *
 | 
        
           |  |  | 557 |          * @method _set
 | 
        
           |  |  | 558 |          * @protected
 | 
        
           |  |  | 559 |          * @chainable
 | 
        
           |  |  | 560 |          *
 | 
        
           |  |  | 561 |          * @param {String} name The name of the attribute.
 | 
        
           |  |  | 562 |          * @param {Any} val The value to set the attribute to.
 | 
        
           |  |  | 563 |          * @param {Object} [opts] Optional data providing the circumstances for the change.
 | 
        
           |  |  | 564 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 565 |          */
 | 
        
           |  |  | 566 |         _set : function(name, val, opts) {
 | 
        
           |  |  | 567 |             return this._setAttr(name, val, opts, true);
 | 
        
           |  |  | 568 |         },
 | 
        
           |  |  | 569 |   | 
        
           |  |  | 570 |         /**
 | 
        
           |  |  | 571 |          * Provides the common implementation for the public set and protected _set methods.
 | 
        
           |  |  | 572 |          *
 | 
        
           |  |  | 573 |          * See <a href="#method_set">set</a> for argument details.
 | 
        
           |  |  | 574 |          *
 | 
        
           |  |  | 575 |          * @method _setAttr
 | 
        
           |  |  | 576 |          * @protected
 | 
        
           |  |  | 577 |          * @chainable
 | 
        
           |  |  | 578 |          *
 | 
        
           |  |  | 579 |          * @param {String} name The name of the attribute.
 | 
        
           |  |  | 580 |          * @param {Any} value The value to set the attribute to.
 | 
        
           |  |  | 581 |          * @param {Object} [opts] Optional data providing the circumstances for the change.
 | 
        
           |  |  | 582 |          * @param {boolean} force If true, allows the caller to set values for
 | 
        
           |  |  | 583 |          * readOnly or writeOnce attributes which have already been set.
 | 
        
           |  |  | 584 |          *
 | 
        
           |  |  | 585 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 586 |          */
 | 
        
           |  |  | 587 |         _setAttr : function(name, val, opts, force)  {
 | 
        
           |  |  | 588 |             var allowSet = true,
 | 
        
           |  |  | 589 |                 state = this._state,
 | 
        
           |  |  | 590 |                 stateProxy = this._stateProxy,
 | 
        
           |  |  | 591 |                 tCfgs = this._tCfgs,
 | 
        
           |  |  | 592 |                 cfg,
 | 
        
           |  |  | 593 |                 initialSet,
 | 
        
           |  |  | 594 |                 strPath,
 | 
        
           |  |  | 595 |                 path,
 | 
        
           |  |  | 596 |                 currVal,
 | 
        
           |  |  | 597 |                 writeOnce,
 | 
        
           |  |  | 598 |                 initializing;
 | 
        
           |  |  | 599 |   | 
        
           |  |  | 600 |             if (name.indexOf(DOT) !== -1) {
 | 
        
           |  |  | 601 |                 strPath = name;
 | 
        
           |  |  | 602 |   | 
        
           |  |  | 603 |                 path = name.split(DOT);
 | 
        
           |  |  | 604 |                 name = path.shift();
 | 
        
           |  |  | 605 |             }
 | 
        
           |  |  | 606 |   | 
        
           |  |  | 607 |             // On Demand - Should be rare - handles out of order valueFn, setter, getter references
 | 
        
           |  |  | 608 |             if (tCfgs && tCfgs[name]) {
 | 
        
           |  |  | 609 |                 this._addOutOfOrder(name, tCfgs[name]);
 | 
        
           |  |  | 610 |             }
 | 
        
           |  |  | 611 |   | 
        
           |  |  | 612 |             cfg = state.data[name] || {};
 | 
        
           |  |  | 613 |   | 
        
           |  |  | 614 |             if (cfg.lazy) {
 | 
        
           |  |  | 615 |                 cfg = cfg.lazy;
 | 
        
           |  |  | 616 |                 this._addLazyAttr(name, cfg);
 | 
        
           |  |  | 617 |             }
 | 
        
           |  |  | 618 |   | 
        
           |  |  | 619 |             initialSet = (cfg.value === undefined);
 | 
        
           |  |  | 620 |   | 
        
           |  |  | 621 |             if (stateProxy && name in stateProxy && !cfg._bypassProxy) {
 | 
        
           |  |  | 622 |                 // TODO: Value is always set for proxy. Can we do any better? Maybe take a snapshot as the initial value for the first call to set?
 | 
        
           |  |  | 623 |                 initialSet = false;
 | 
        
           |  |  | 624 |             }
 | 
        
           |  |  | 625 |   | 
        
           |  |  | 626 |             writeOnce = cfg.writeOnce;
 | 
        
           |  |  | 627 |             initializing = cfg.initializing;
 | 
        
           |  |  | 628 |   | 
        
           |  |  | 629 |             if (!initialSet && !force) {
 | 
        
           |  |  | 630 |   | 
        
           |  |  | 631 |                 if (writeOnce) {
 | 
        
           |  |  | 632 |                     Y.log('Set attribute:' + name + ', aborted; Attribute is writeOnce', 'warn', 'attribute');
 | 
        
           |  |  | 633 |                     allowSet = false;
 | 
        
           |  |  | 634 |                 }
 | 
        
           |  |  | 635 |   | 
        
           |  |  | 636 |                 if (cfg.readOnly) {
 | 
        
           |  |  | 637 |                     Y.log('Set attribute:' + name + ', aborted; Attribute is readOnly', 'warn', 'attribute');
 | 
        
           |  |  | 638 |                     allowSet = false;
 | 
        
           |  |  | 639 |                 }
 | 
        
           |  |  | 640 |             }
 | 
        
           |  |  | 641 |   | 
        
           |  |  | 642 |             if (!initializing && !force && writeOnce === INIT_ONLY) {
 | 
        
           |  |  | 643 |                 Y.log('Set attribute:' + name + ', aborted; Attribute is writeOnce: "initOnly"', 'warn', 'attribute');
 | 
        
           |  |  | 644 |                 allowSet = false;
 | 
        
           |  |  | 645 |             }
 | 
        
           |  |  | 646 |   | 
        
           |  |  | 647 |             if (allowSet) {
 | 
        
           |  |  | 648 |                 // Don't need currVal if initialSet (might fail in custom getter if it always expects a non-undefined/non-null value)
 | 
        
           |  |  | 649 |                 if (!initialSet) {
 | 
        
           |  |  | 650 |                     currVal =  this.get(name);
 | 
        
           |  |  | 651 |                 }
 | 
        
           |  |  | 652 |   | 
        
           |  |  | 653 |                 if (path) {
 | 
        
           |  |  | 654 |                    val = O.setValue(Y.clone(currVal), path, val);
 | 
        
           |  |  | 655 |   | 
        
           |  |  | 656 |                    if (val === undefined) {
 | 
        
           |  |  | 657 |                        Y.log('Set attribute path:' + strPath + ', aborted; Path is invalid', 'warn', 'attribute');
 | 
        
           |  |  | 658 |                        allowSet = false;
 | 
        
           |  |  | 659 |                    }
 | 
        
           |  |  | 660 |                 }
 | 
        
           |  |  | 661 |   | 
        
           |  |  | 662 |                 if (allowSet) {
 | 
        
           |  |  | 663 |                     if (!this._fireAttrChange || initializing) {
 | 
        
           |  |  | 664 |                         this._setAttrVal(name, strPath, currVal, val, opts, cfg);
 | 
        
           |  |  | 665 |                     } else {
 | 
        
           |  |  | 666 |                         // HACK - no real reason core needs to know about _fireAttrChange, but
 | 
        
           |  |  | 667 |                         // it adds fn hops if we want to break it out. Not sure it's worth it for this critical path
 | 
        
           |  |  | 668 |                         this._fireAttrChange(name, strPath, currVal, val, opts, cfg);
 | 
        
           |  |  | 669 |                     }
 | 
        
           |  |  | 670 |                 }
 | 
        
           |  |  | 671 |             }
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 |             return this;
 | 
        
           |  |  | 674 |         },
 | 
        
           |  |  | 675 |   | 
        
           |  |  | 676 |         /**
 | 
        
           |  |  | 677 |          * Utility method used by get/set to add attributes
 | 
        
           |  |  | 678 |          * encountered out of order when calling addAttrs().
 | 
        
           |  |  | 679 |          *
 | 
        
           |  |  | 680 |          * For example, if:
 | 
        
           |  |  | 681 |          *
 | 
        
           |  |  | 682 |          *     this.addAttrs({
 | 
        
           |  |  | 683 |          *          foo: {
 | 
        
           |  |  | 684 |          *              setter: function() {
 | 
        
           |  |  | 685 |          *                 // make sure this bar is available when foo is added
 | 
        
           |  |  | 686 |          *                 this.get("bar");
 | 
        
           |  |  | 687 |          *              }
 | 
        
           |  |  | 688 |          *          },
 | 
        
           |  |  | 689 |          *          bar: {
 | 
        
           |  |  | 690 |          *              value: ...
 | 
        
           |  |  | 691 |          *          }
 | 
        
           |  |  | 692 |          *     });
 | 
        
           |  |  | 693 |          *
 | 
        
           |  |  | 694 |          * @method _addOutOfOrder
 | 
        
           |  |  | 695 |          * @private
 | 
        
           |  |  | 696 |          * @param name {String} attribute name
 | 
        
           |  |  | 697 |          * @param cfg {Object} attribute configuration
 | 
        
           |  |  | 698 |          */
 | 
        
           |  |  | 699 |         _addOutOfOrder : function(name, cfg) {
 | 
        
           |  |  | 700 |   | 
        
           |  |  | 701 |             var attrs = {};
 | 
        
           |  |  | 702 |             attrs[name] = cfg;
 | 
        
           |  |  | 703 |   | 
        
           |  |  | 704 |             delete this._tCfgs[name];
 | 
        
           |  |  | 705 |   | 
        
           |  |  | 706 |             // TODO: The original code went through addAttrs, so
 | 
        
           |  |  | 707 |             // sticking with it for this pass. Seems like we could
 | 
        
           |  |  | 708 |             // just jump straight to _addAttr() and get some perf
 | 
        
           |  |  | 709 |             // improvement.
 | 
        
           |  |  | 710 |             this._addAttrs(attrs, this._tVals);
 | 
        
           |  |  | 711 |         },
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 |         /**
 | 
        
           |  |  | 714 |          * Provides the common implementation for the public get method,
 | 
        
           |  |  | 715 |          * allowing Attribute hosts to over-ride either method.
 | 
        
           |  |  | 716 |          *
 | 
        
           |  |  | 717 |          * See <a href="#method_get">get</a> for argument details.
 | 
        
           |  |  | 718 |          *
 | 
        
           |  |  | 719 |          * @method _getAttr
 | 
        
           |  |  | 720 |          * @protected
 | 
        
           |  |  | 721 |          * @chainable
 | 
        
           |  |  | 722 |          *
 | 
        
           |  |  | 723 |          * @param {String} name The name of the attribute.
 | 
        
           |  |  | 724 |          * @return {Any} The value of the attribute.
 | 
        
           |  |  | 725 |          */
 | 
        
           |  |  | 726 |         _getAttr : function(name) {
 | 
        
           |  |  | 727 |             var fullName = name,
 | 
        
           |  |  | 728 |                 tCfgs = this._tCfgs,
 | 
        
           |  |  | 729 |                 path,
 | 
        
           |  |  | 730 |                 getter,
 | 
        
           |  |  | 731 |                 val,
 | 
        
           |  |  | 732 |                 attrCfg;
 | 
        
           |  |  | 733 |   | 
        
           |  |  | 734 |             if (name.indexOf(DOT) !== -1) {
 | 
        
           |  |  | 735 |                 path = name.split(DOT);
 | 
        
           |  |  | 736 |                 name = path.shift();
 | 
        
           |  |  | 737 |             }
 | 
        
           |  |  | 738 |   | 
        
           |  |  | 739 |             // On Demand - Should be rare - handles out of
 | 
        
           |  |  | 740 |             // order valueFn, setter, getter references
 | 
        
           |  |  | 741 |             if (tCfgs && tCfgs[name]) {
 | 
        
           |  |  | 742 |                 this._addOutOfOrder(name, tCfgs[name]);
 | 
        
           |  |  | 743 |             }
 | 
        
           |  |  | 744 |   | 
        
           |  |  | 745 |             attrCfg = this._state.data[name] || {};
 | 
        
           |  |  | 746 |   | 
        
           |  |  | 747 |             // Lazy Init
 | 
        
           |  |  | 748 |             if (attrCfg.lazy) {
 | 
        
           |  |  | 749 |                 attrCfg = attrCfg.lazy;
 | 
        
           |  |  | 750 |                 this._addLazyAttr(name, attrCfg);
 | 
        
           |  |  | 751 |             }
 | 
        
           |  |  | 752 |   | 
        
           |  |  | 753 |             val = this._getStateVal(name, attrCfg);
 | 
        
           |  |  | 754 |   | 
        
           |  |  | 755 |             getter = attrCfg.getter;
 | 
        
           |  |  | 756 |   | 
        
           |  |  | 757 |             if (getter && !getter.call) {
 | 
        
           |  |  | 758 |                 getter = this[getter];
 | 
        
           |  |  | 759 |             }
 | 
        
           |  |  | 760 |   | 
        
           |  |  | 761 |             val = (getter) ? getter.call(this, val, fullName) : val;
 | 
        
           |  |  | 762 |             val = (path) ? O.getValue(val, path) : val;
 | 
        
           |  |  | 763 |   | 
        
           |  |  | 764 |             return val;
 | 
        
           |  |  | 765 |         },
 | 
        
           |  |  | 766 |   | 
        
           |  |  | 767 |         /**
 | 
        
           |  |  | 768 |          * Gets the stored value for the attribute, from either the
 | 
        
           |  |  | 769 |          * internal state object, or the state proxy if it exits
 | 
        
           |  |  | 770 |          *
 | 
        
           |  |  | 771 |          * @method _getStateVal
 | 
        
           |  |  | 772 |          * @private
 | 
        
           |  |  | 773 |          * @param {String} name The name of the attribute
 | 
        
           |  |  | 774 |          * @param {Object} [cfg] Optional config hash for the attribute. This is added for performance along the critical path,
 | 
        
           |  |  | 775 |          * where the calling method has already obtained the config from state.
 | 
        
           |  |  | 776 |          *
 | 
        
           |  |  | 777 |          * @return {Any} The stored value of the attribute
 | 
        
           |  |  | 778 |          */
 | 
        
           |  |  | 779 |         _getStateVal : function(name, cfg) {
 | 
        
           |  |  | 780 |             var stateProxy = this._stateProxy;
 | 
        
           |  |  | 781 |   | 
        
           |  |  | 782 |             if (!cfg) {
 | 
        
           |  |  | 783 |                 cfg = this._state.getAll(name) || {};
 | 
        
           |  |  | 784 |             }
 | 
        
           |  |  | 785 |   | 
        
           |  |  | 786 |             return (stateProxy && (name in stateProxy) && !(cfg._bypassProxy)) ? stateProxy[name] : cfg.value;
 | 
        
           |  |  | 787 |         },
 | 
        
           |  |  | 788 |   | 
        
           |  |  | 789 |         /**
 | 
        
           |  |  | 790 |          * Sets the stored value for the attribute, in either the
 | 
        
           |  |  | 791 |          * internal state object, or the state proxy if it exits
 | 
        
           |  |  | 792 |          *
 | 
        
           |  |  | 793 |          * @method _setStateVal
 | 
        
           |  |  | 794 |          * @private
 | 
        
           |  |  | 795 |          * @param {String} name The name of the attribute
 | 
        
           |  |  | 796 |          * @param {Any} value The value of the attribute
 | 
        
           |  |  | 797 |          */
 | 
        
           |  |  | 798 |         _setStateVal : function(name, value) {
 | 
        
           |  |  | 799 |             var stateProxy = this._stateProxy;
 | 
        
           |  |  | 800 |             if (stateProxy && (name in stateProxy) && !this._state.get(name, BYPASS_PROXY)) {
 | 
        
           |  |  | 801 |                 stateProxy[name] = value;
 | 
        
           |  |  | 802 |             } else {
 | 
        
           |  |  | 803 |                 this._state.add(name, VALUE, value);
 | 
        
           |  |  | 804 |             }
 | 
        
           |  |  | 805 |         },
 | 
        
           |  |  | 806 |   | 
        
           |  |  | 807 |         /**
 | 
        
           |  |  | 808 |          * Updates the stored value of the attribute in the privately held State object,
 | 
        
           |  |  | 809 |          * if validation and setter passes.
 | 
        
           |  |  | 810 |          *
 | 
        
           |  |  | 811 |          * @method _setAttrVal
 | 
        
           |  |  | 812 |          * @private
 | 
        
           |  |  | 813 |          * @param {String} attrName The attribute name.
 | 
        
           |  |  | 814 |          * @param {String} subAttrName The sub-attribute name, if setting a sub-attribute property ("x.y.z").
 | 
        
           |  |  | 815 |          * @param {Any} prevVal The currently stored value of the attribute.
 | 
        
           |  |  | 816 |          * @param {Any} newVal The value which is going to be stored.
 | 
        
           |  |  | 817 |          * @param {Object} [opts] Optional data providing the circumstances for the change.
 | 
        
           |  |  | 818 |          * @param {Object} [attrCfg] Optional config hash for the attribute. This is added for performance along the critical path,
 | 
        
           |  |  | 819 |          * where the calling method has already obtained the config from state.
 | 
        
           |  |  | 820 |          *
 | 
        
           |  |  | 821 |          * @return {Boolean} true if the new attribute value was stored, false if not.
 | 
        
           |  |  | 822 |          */
 | 
        
           |  |  | 823 |         _setAttrVal : function(attrName, subAttrName, prevVal, newVal, opts, attrCfg) {
 | 
        
           |  |  | 824 |   | 
        
           |  |  | 825 |             var host = this,
 | 
        
           |  |  | 826 |                 allowSet = true,
 | 
        
           |  |  | 827 |                 cfg = attrCfg || this._state.data[attrName] || {},
 | 
        
           |  |  | 828 |                 validator = cfg.validator,
 | 
        
           |  |  | 829 |                 setter = cfg.setter,
 | 
        
           |  |  | 830 |                 initializing = cfg.initializing,
 | 
        
           |  |  | 831 |                 prevRawVal = this._getStateVal(attrName, cfg),
 | 
        
           |  |  | 832 |                 name = subAttrName || attrName,
 | 
        
           |  |  | 833 |                 retVal,
 | 
        
           |  |  | 834 |                 valid;
 | 
        
           |  |  | 835 |   | 
        
           |  |  | 836 |             if (validator) {
 | 
        
           |  |  | 837 |                 if (!validator.call) {
 | 
        
           |  |  | 838 |                     // Assume string - trying to keep critical path tight, so avoiding Lang check
 | 
        
           |  |  | 839 |                     validator = this[validator];
 | 
        
           |  |  | 840 |                 }
 | 
        
           |  |  | 841 |                 if (validator) {
 | 
        
           |  |  | 842 |                     valid = validator.call(host, newVal, name, opts);
 | 
        
           |  |  | 843 |   | 
        
           |  |  | 844 |                     if (!valid && initializing) {
 | 
        
           |  |  | 845 |                         newVal = cfg.defaultValue;
 | 
        
           |  |  | 846 |                         valid = true; // Assume it's valid, for perf.
 | 
        
           |  |  | 847 |                     }
 | 
        
           |  |  | 848 |                 }
 | 
        
           |  |  | 849 |             }
 | 
        
           |  |  | 850 |   | 
        
           |  |  | 851 |             if (!validator || valid) {
 | 
        
           |  |  | 852 |                 if (setter) {
 | 
        
           |  |  | 853 |                     if (!setter.call) {
 | 
        
           |  |  | 854 |                         // Assume string - trying to keep critical path tight, so avoiding Lang check
 | 
        
           |  |  | 855 |                         setter = this[setter];
 | 
        
           |  |  | 856 |                     }
 | 
        
           |  |  | 857 |                     if (setter) {
 | 
        
           |  |  | 858 |                         retVal = setter.call(host, newVal, name, opts);
 | 
        
           |  |  | 859 |   | 
        
           |  |  | 860 |                         if (retVal === INVALID_VALUE) {
 | 
        
           |  |  | 861 |                             if (initializing) {
 | 
        
           |  |  | 862 |                                 Y.log('Attribute: ' + attrName + ', setter returned Attribute.INVALID_VALUE for value:' + newVal + ', initializing to default value', 'warn', 'attribute');
 | 
        
           |  |  | 863 |                                 newVal = cfg.defaultValue;
 | 
        
           |  |  | 864 |                             } else {
 | 
        
           |  |  | 865 |                                 Y.log('Attribute: ' + attrName + ', setter returned Attribute.INVALID_VALUE for value:' + newVal, 'warn', 'attribute');
 | 
        
           |  |  | 866 |                                 allowSet = false;
 | 
        
           |  |  | 867 |                             }
 | 
        
           |  |  | 868 |                         } else if (retVal !== undefined){
 | 
        
           |  |  | 869 |                             Y.log('Attribute: ' + attrName + ', raw value: ' + newVal + ' modified by setter to:' + retVal, 'info', 'attribute');
 | 
        
           |  |  | 870 |                             newVal = retVal;
 | 
        
           |  |  | 871 |                         }
 | 
        
           |  |  | 872 |                     }
 | 
        
           |  |  | 873 |                 }
 | 
        
           |  |  | 874 |   | 
        
           |  |  | 875 |                 if (allowSet) {
 | 
        
           |  |  | 876 |                     if(!subAttrName && (newVal === prevRawVal) && !Lang.isObject(newVal)) {
 | 
        
           |  |  | 877 |                         Y.log('Attribute: ' + attrName + ', value unchanged:' + newVal, 'warn', 'attribute');
 | 
        
           |  |  | 878 |                         allowSet = false;
 | 
        
           |  |  | 879 |                     } else {
 | 
        
           |  |  | 880 |                         // Store value
 | 
        
           |  |  | 881 |                         if (!(INIT_VALUE in cfg)) {
 | 
        
           |  |  | 882 |                             cfg.initValue = newVal;
 | 
        
           |  |  | 883 |                         }
 | 
        
           |  |  | 884 |                         host._setStateVal(attrName, newVal);
 | 
        
           |  |  | 885 |                     }
 | 
        
           |  |  | 886 |                 }
 | 
        
           |  |  | 887 |   | 
        
           |  |  | 888 |             } else {
 | 
        
           |  |  | 889 |                 Y.log('Attribute:' + attrName + ', Validation failed for value:' + newVal, 'warn', 'attribute');
 | 
        
           |  |  | 890 |                 allowSet = false;
 | 
        
           |  |  | 891 |             }
 | 
        
           |  |  | 892 |   | 
        
           |  |  | 893 |             return allowSet;
 | 
        
           |  |  | 894 |         },
 | 
        
           |  |  | 895 |   | 
        
           |  |  | 896 |         /**
 | 
        
           |  |  | 897 |          * Sets multiple attribute values.
 | 
        
           |  |  | 898 |          *
 | 
        
           |  |  | 899 |          * @method setAttrs
 | 
        
           |  |  | 900 |          * @param {Object} attrs  An object with attributes name/value pairs.
 | 
        
           |  |  | 901 |          * @param {Object} [opts] Optional data providing the circumstances for the change.
 | 
        
           |  |  | 902 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 903 |          * @chainable
 | 
        
           |  |  | 904 |          */
 | 
        
           |  |  | 905 |         setAttrs : function(attrs, opts) {
 | 
        
           |  |  | 906 |             return this._setAttrs(attrs, opts);
 | 
        
           |  |  | 907 |         },
 | 
        
           |  |  | 908 |   | 
        
           |  |  | 909 |         /**
 | 
        
           |  |  | 910 |          * Implementation behind the public setAttrs method, to set multiple attribute values.
 | 
        
           |  |  | 911 |          *
 | 
        
           |  |  | 912 |          * @method _setAttrs
 | 
        
           |  |  | 913 |          * @protected
 | 
        
           |  |  | 914 |          * @param {Object} attrs  An object with attributes name/value pairs.
 | 
        
           |  |  | 915 |          * @param {Object} [opts] Optional data providing the circumstances for the change
 | 
        
           |  |  | 916 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 917 |          * @chainable
 | 
        
           |  |  | 918 |          */
 | 
        
           |  |  | 919 |         _setAttrs : function(attrs, opts) {
 | 
        
           |  |  | 920 |             var attr;
 | 
        
           |  |  | 921 |             for (attr in attrs) {
 | 
        
           |  |  | 922 |                 if ( attrs.hasOwnProperty(attr) ) {
 | 
        
           |  |  | 923 |                     this.set(attr, attrs[attr], opts);
 | 
        
           |  |  | 924 |                 }
 | 
        
           |  |  | 925 |             }
 | 
        
           |  |  | 926 |             return this;
 | 
        
           |  |  | 927 |         },
 | 
        
           |  |  | 928 |   | 
        
           |  |  | 929 |         /**
 | 
        
           |  |  | 930 |          * Gets multiple attribute values.
 | 
        
           |  |  | 931 |          *
 | 
        
           |  |  | 932 |          * @method getAttrs
 | 
        
           |  |  | 933 |          * @param {String[]|Boolean} attrs Optional. An array of attribute names. If omitted, all attribute values are
 | 
        
           |  |  | 934 |          * returned. If set to true, all attributes modified from their initial values are returned.
 | 
        
           |  |  | 935 |          * @return {Object} An object with attribute name/value pairs.
 | 
        
           |  |  | 936 |          */
 | 
        
           |  |  | 937 |         getAttrs : function(attrs) {
 | 
        
           |  |  | 938 |             return this._getAttrs(attrs);
 | 
        
           |  |  | 939 |         },
 | 
        
           |  |  | 940 |   | 
        
           |  |  | 941 |         /**
 | 
        
           |  |  | 942 |          * Implementation behind the public getAttrs method, to get multiple attribute values.
 | 
        
           |  |  | 943 |          *
 | 
        
           |  |  | 944 |          * @method _getAttrs
 | 
        
           |  |  | 945 |          * @protected
 | 
        
           |  |  | 946 |          * @param {String[]|Boolean} attrs Optional. An array of attribute names. If omitted, all attribute values are
 | 
        
           |  |  | 947 |          * returned. If set to true, all attributes modified from their initial values are returned.
 | 
        
           |  |  | 948 |          * @return {Object} An object with attribute name/value pairs.
 | 
        
           |  |  | 949 |          */
 | 
        
           |  |  | 950 |         _getAttrs : function(attrs) {
 | 
        
           |  |  | 951 |             var obj = {},
 | 
        
           |  |  | 952 |                 attr, i, len,
 | 
        
           |  |  | 953 |                 modifiedOnly = (attrs === true);
 | 
        
           |  |  | 954 |   | 
        
           |  |  | 955 |             // TODO - figure out how to get all "added"
 | 
        
           |  |  | 956 |             if (!attrs || modifiedOnly) {
 | 
        
           |  |  | 957 |                 attrs = O.keys(this._state.data);
 | 
        
           |  |  | 958 |             }
 | 
        
           |  |  | 959 |   | 
        
           |  |  | 960 |             for (i = 0, len = attrs.length; i < len; i++) {
 | 
        
           |  |  | 961 |                 attr = attrs[i];
 | 
        
           |  |  | 962 |   | 
        
           |  |  | 963 |                 if (!modifiedOnly || this._getStateVal(attr) != this._state.get(attr, INIT_VALUE)) {
 | 
        
           |  |  | 964 |                     // Go through get, to honor cloning/normalization
 | 
        
           |  |  | 965 |                     obj[attr] = this.get(attr);
 | 
        
           |  |  | 966 |                 }
 | 
        
           |  |  | 967 |             }
 | 
        
           |  |  | 968 |   | 
        
           |  |  | 969 |             return obj;
 | 
        
           |  |  | 970 |         },
 | 
        
           |  |  | 971 |   | 
        
           |  |  | 972 |         /**
 | 
        
           |  |  | 973 |          * Configures a group of attributes, and sets initial values.
 | 
        
           |  |  | 974 |          *
 | 
        
           |  |  | 975 |          * <p>
 | 
        
           |  |  | 976 |          * <strong>NOTE:</strong> This method does not isolate the configuration object by merging/cloning.
 | 
        
           |  |  | 977 |          * The caller is responsible for merging/cloning the configuration object if required.
 | 
        
           |  |  | 978 |          * </p>
 | 
        
           |  |  | 979 |          *
 | 
        
           |  |  | 980 |          * @method addAttrs
 | 
        
           |  |  | 981 |          * @chainable
 | 
        
           |  |  | 982 |          *
 | 
        
           |  |  | 983 |          * @param {Object} cfgs An object with attribute name/configuration pairs.
 | 
        
           |  |  | 984 |          * @param {Object} values An object with attribute name/value pairs, defining the initial values to apply.
 | 
        
           |  |  | 985 |          * Values defined in the cfgs argument will be over-written by values in this argument unless defined as read only.
 | 
        
           |  |  | 986 |          * @param {boolean} lazy Whether or not to delay the intialization of these attributes until the first call to get/set.
 | 
        
           |  |  | 987 |          * Individual attributes can over-ride this behavior by defining a lazyAdd configuration property in their configuration.
 | 
        
           |  |  | 988 |          * See <a href="#method_addAttr">addAttr</a>.
 | 
        
           |  |  | 989 |          *
 | 
        
           |  |  | 990 |          * @return {Object} A reference to the host object.
 | 
        
           |  |  | 991 |          */
 | 
        
           |  |  | 992 |         addAttrs : function(cfgs, values, lazy) {
 | 
        
           |  |  | 993 |             if (cfgs) {
 | 
        
           |  |  | 994 |                 this._tCfgs = cfgs;
 | 
        
           |  |  | 995 |                 this._tVals = (values) ? this._normAttrVals(values) : null;
 | 
        
           |  |  | 996 |                 this._addAttrs(cfgs, this._tVals, lazy);
 | 
        
           |  |  | 997 |                 this._tCfgs = this._tVals = null;
 | 
        
           |  |  | 998 |             }
 | 
        
           |  |  | 999 |   | 
        
           |  |  | 1000 |             return this;
 | 
        
           |  |  | 1001 |         },
 | 
        
           |  |  | 1002 |   | 
        
           |  |  | 1003 |         /**
 | 
        
           |  |  | 1004 |          * Implementation behind the public addAttrs method.
 | 
        
           |  |  | 1005 |          *
 | 
        
           |  |  | 1006 |          * This method is invoked directly by get if it encounters a scenario
 | 
        
           |  |  | 1007 |          * in which an attribute's valueFn attempts to obtain the
 | 
        
           |  |  | 1008 |          * value an attribute in the same group of attributes, which has not yet
 | 
        
           |  |  | 1009 |          * been added (on demand initialization).
 | 
        
           |  |  | 1010 |          *
 | 
        
           |  |  | 1011 |          * @method _addAttrs
 | 
        
           |  |  | 1012 |          * @private
 | 
        
           |  |  | 1013 |          * @param {Object} cfgs An object with attribute name/configuration pairs.
 | 
        
           |  |  | 1014 |          * @param {Object} values An object with attribute name/value pairs, defining the initial values to apply.
 | 
        
           |  |  | 1015 |          * Values defined in the cfgs argument will be over-written by values in this argument unless defined as read only.
 | 
        
           |  |  | 1016 |          * @param {boolean} lazy Whether or not to delay the intialization of these attributes until the first call to get/set.
 | 
        
           |  |  | 1017 |          * Individual attributes can over-ride this behavior by defining a lazyAdd configuration property in their configuration.
 | 
        
           |  |  | 1018 |          * See <a href="#method_addAttr">addAttr</a>.
 | 
        
           |  |  | 1019 |          */
 | 
        
           |  |  | 1020 |         _addAttrs : function(cfgs, values, lazy) {
 | 
        
           |  |  | 1021 |             var tCfgs = this._tCfgs,
 | 
        
           |  |  | 1022 |                 tVals = this._tVals,
 | 
        
           |  |  | 1023 |                 attr,
 | 
        
           |  |  | 1024 |                 attrCfg,
 | 
        
           |  |  | 1025 |                 value;
 | 
        
           |  |  | 1026 |   | 
        
           |  |  | 1027 |             for (attr in cfgs) {
 | 
        
           |  |  | 1028 |                 if (cfgs.hasOwnProperty(attr)) {
 | 
        
           |  |  | 1029 |   | 
        
           |  |  | 1030 |                     // Not Merging. Caller is responsible for isolating configs
 | 
        
           |  |  | 1031 |                     attrCfg = cfgs[attr];
 | 
        
           |  |  | 1032 |                     attrCfg.defaultValue = attrCfg.value;
 | 
        
           |  |  | 1033 |   | 
        
           |  |  | 1034 |                     // Handle simple, complex and user values, accounting for read-only
 | 
        
           |  |  | 1035 |                     value = this._getAttrInitVal(attr, attrCfg, tVals);
 | 
        
           |  |  | 1036 |   | 
        
           |  |  | 1037 |                     if (value !== undefined) {
 | 
        
           |  |  | 1038 |                         attrCfg.value = value;
 | 
        
           |  |  | 1039 |                     }
 | 
        
           |  |  | 1040 |   | 
        
           |  |  | 1041 |                     if (tCfgs[attr]) {
 | 
        
           |  |  | 1042 |                         tCfgs[attr] = undefined;
 | 
        
           |  |  | 1043 |                     }
 | 
        
           |  |  | 1044 |   | 
        
           |  |  | 1045 |                     this.addAttr(attr, attrCfg, lazy);
 | 
        
           |  |  | 1046 |                 }
 | 
        
           |  |  | 1047 |             }
 | 
        
           |  |  | 1048 |         },
 | 
        
           |  |  | 1049 |   | 
        
           |  |  | 1050 |         /**
 | 
        
           |  |  | 1051 |          * Utility method to protect an attribute configuration
 | 
        
           |  |  | 1052 |          * hash, by merging the entire object and the individual
 | 
        
           |  |  | 1053 |          * attr config objects.
 | 
        
           |  |  | 1054 |          *
 | 
        
           |  |  | 1055 |          * @method _protectAttrs
 | 
        
           |  |  | 1056 |          * @protected
 | 
        
           |  |  | 1057 |          * @param {Object} attrs A hash of attribute to configuration object pairs.
 | 
        
           |  |  | 1058 |          * @return {Object} A protected version of the attrs argument.
 | 
        
           |  |  | 1059 |          * @deprecated Use `AttributeCore.protectAttrs()` or
 | 
        
           |  |  | 1060 |          *   `Attribute.protectAttrs()` which are the same static utility method.
 | 
        
           |  |  | 1061 |          */
 | 
        
           |  |  | 1062 |         _protectAttrs : AttributeCore.protectAttrs,
 | 
        
           |  |  | 1063 |   | 
        
           |  |  | 1064 |         /**
 | 
        
           |  |  | 1065 |          * Utility method to normalize attribute values. The base implementation
 | 
        
           |  |  | 1066 |          * simply merges the hash to protect the original.
 | 
        
           |  |  | 1067 |          *
 | 
        
           |  |  | 1068 |          * @method _normAttrVals
 | 
        
           |  |  | 1069 |          * @param {Object} valueHash An object with attribute name/value pairs
 | 
        
           |  |  | 1070 |          *
 | 
        
           |  |  | 1071 |          * @return {Object} An object literal with 2 properties - "simple" and "complex",
 | 
        
           |  |  | 1072 |          * containing simple and complex attribute values respectively keyed
 | 
        
           |  |  | 1073 |          * by the top level attribute name, or null, if valueHash is falsey.
 | 
        
           |  |  | 1074 |          *
 | 
        
           |  |  | 1075 |          * @private
 | 
        
           |  |  | 1076 |          */
 | 
        
           |  |  | 1077 |         _normAttrVals : function(valueHash) {
 | 
        
           |  |  | 1078 |             var vals,
 | 
        
           |  |  | 1079 |                 subvals,
 | 
        
           |  |  | 1080 |                 path,
 | 
        
           |  |  | 1081 |                 attr,
 | 
        
           |  |  | 1082 |                 v, k;
 | 
        
           |  |  | 1083 |   | 
        
           |  |  | 1084 |             if (!valueHash) {
 | 
        
           |  |  | 1085 |                 return null;
 | 
        
           |  |  | 1086 |             }
 | 
        
           |  |  | 1087 |   | 
        
           |  |  | 1088 |             vals = {};
 | 
        
           |  |  | 1089 |   | 
        
           |  |  | 1090 |             for (k in valueHash) {
 | 
        
           |  |  | 1091 |                 if (valueHash.hasOwnProperty(k)) {
 | 
        
           |  |  | 1092 |                     if (k.indexOf(DOT) !== -1) {
 | 
        
           |  |  | 1093 |                         path = k.split(DOT);
 | 
        
           |  |  | 1094 |                         attr = path.shift();
 | 
        
           |  |  | 1095 |   | 
        
           |  |  | 1096 |                         subvals = subvals || {};
 | 
        
           |  |  | 1097 |   | 
        
           |  |  | 1098 |                         v = subvals[attr] = subvals[attr] || [];
 | 
        
           |  |  | 1099 |                         v[v.length] = {
 | 
        
           |  |  | 1100 |                             path : path,
 | 
        
           |  |  | 1101 |                             value: valueHash[k]
 | 
        
           |  |  | 1102 |                         };
 | 
        
           |  |  | 1103 |                     } else {
 | 
        
           |  |  | 1104 |                         vals[k] = valueHash[k];
 | 
        
           |  |  | 1105 |                     }
 | 
        
           |  |  | 1106 |                 }
 | 
        
           |  |  | 1107 |             }
 | 
        
           |  |  | 1108 |   | 
        
           |  |  | 1109 |             return { simple:vals, complex:subvals };
 | 
        
           |  |  | 1110 |         },
 | 
        
           |  |  | 1111 |   | 
        
           |  |  | 1112 |         /**
 | 
        
           |  |  | 1113 |          * Returns the initial value of the given attribute from
 | 
        
           |  |  | 1114 |          * either the default configuration provided, or the
 | 
        
           |  |  | 1115 |          * over-ridden value if it exists in the set of initValues
 | 
        
           |  |  | 1116 |          * provided and the attribute is not read-only.
 | 
        
           |  |  | 1117 |          *
 | 
        
           |  |  | 1118 |          * @param {String} attr The name of the attribute
 | 
        
           |  |  | 1119 |          * @param {Object} cfg The attribute configuration object
 | 
        
           |  |  | 1120 |          * @param {Object} initValues The object with simple and complex attribute name/value pairs returned from _normAttrVals
 | 
        
           |  |  | 1121 |          *
 | 
        
           |  |  | 1122 |          * @return {Any} The initial value of the attribute.
 | 
        
           |  |  | 1123 |          *
 | 
        
           |  |  | 1124 |          * @method _getAttrInitVal
 | 
        
           |  |  | 1125 |          * @private
 | 
        
           |  |  | 1126 |          */
 | 
        
           |  |  | 1127 |         _getAttrInitVal : function(attr, cfg, initValues) {
 | 
        
           |  |  | 1128 |             var val = cfg.value,
 | 
        
           |  |  | 1129 |                 valFn = cfg.valueFn,
 | 
        
           |  |  | 1130 |                 tmpVal,
 | 
        
           |  |  | 1131 |                 initValSet = false,
 | 
        
           |  |  | 1132 |                 readOnly = cfg.readOnly,
 | 
        
           |  |  | 1133 |                 simple,
 | 
        
           |  |  | 1134 |                 complex,
 | 
        
           |  |  | 1135 |                 i,
 | 
        
           |  |  | 1136 |                 l,
 | 
        
           |  |  | 1137 |                 path,
 | 
        
           |  |  | 1138 |                 subval,
 | 
        
           |  |  | 1139 |                 subvals;
 | 
        
           |  |  | 1140 |   | 
        
           |  |  | 1141 |             if (!readOnly && initValues) {
 | 
        
           |  |  | 1142 |                 // Simple Attributes
 | 
        
           |  |  | 1143 |                 simple = initValues.simple;
 | 
        
           |  |  | 1144 |                 if (simple && simple.hasOwnProperty(attr)) {
 | 
        
           |  |  | 1145 |                     val = simple[attr];
 | 
        
           |  |  | 1146 |                     initValSet = true;
 | 
        
           |  |  | 1147 |                 }
 | 
        
           |  |  | 1148 |             }
 | 
        
           |  |  | 1149 |   | 
        
           |  |  | 1150 |             if (valFn && !initValSet) {
 | 
        
           |  |  | 1151 |                 if (!valFn.call) {
 | 
        
           |  |  | 1152 |                     valFn = this[valFn];
 | 
        
           |  |  | 1153 |                 }
 | 
        
           |  |  | 1154 |                 if (valFn) {
 | 
        
           |  |  | 1155 |                     tmpVal = valFn.call(this, attr);
 | 
        
           |  |  | 1156 |                     val = tmpVal;
 | 
        
           |  |  | 1157 |                 }
 | 
        
           |  |  | 1158 |             }
 | 
        
           |  |  | 1159 |   | 
        
           |  |  | 1160 |             if (!readOnly && initValues) {
 | 
        
           |  |  | 1161 |   | 
        
           |  |  | 1162 |                 // Complex Attributes (complex values applied, after simple, in case both are set)
 | 
        
           |  |  | 1163 |                 complex = initValues.complex;
 | 
        
           |  |  | 1164 |   | 
        
           |  |  | 1165 |                 if (complex && complex.hasOwnProperty(attr) && (val !== undefined) && (val !== null)) {
 | 
        
           |  |  | 1166 |                     subvals = complex[attr];
 | 
        
           |  |  | 1167 |                     for (i = 0, l = subvals.length; i < l; ++i) {
 | 
        
           |  |  | 1168 |                         path = subvals[i].path;
 | 
        
           |  |  | 1169 |                         subval = subvals[i].value;
 | 
        
           |  |  | 1170 |                         O.setValue(val, path, subval);
 | 
        
           |  |  | 1171 |                     }
 | 
        
           |  |  | 1172 |                 }
 | 
        
           |  |  | 1173 |             }
 | 
        
           |  |  | 1174 |   | 
        
           |  |  | 1175 |             return val;
 | 
        
           |  |  | 1176 |         },
 | 
        
           |  |  | 1177 |   | 
        
           |  |  | 1178 |         /**
 | 
        
           |  |  | 1179 |          * Utility method to set up initial attributes defined during construction,
 | 
        
           |  |  | 1180 |          * either through the constructor.ATTRS property, or explicitly passed in.
 | 
        
           |  |  | 1181 |          *
 | 
        
           |  |  | 1182 |          * @method _initAttrs
 | 
        
           |  |  | 1183 |          * @protected
 | 
        
           |  |  | 1184 |          * @param attrs {Object} The attributes to add during construction (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 1185 |          *        These can also be defined on the constructor being augmented with Attribute by defining the ATTRS property on the constructor.
 | 
        
           |  |  | 1186 |          * @param values {Object} The initial attribute values to apply (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 1187 |          *        These are not merged/cloned. The caller is responsible for isolating user provided values if required.
 | 
        
           |  |  | 1188 |          * @param lazy {boolean} Whether or not to add attributes lazily (passed through to <a href="#method_addAttrs">addAttrs</a>).
 | 
        
           |  |  | 1189 |          */
 | 
        
           |  |  | 1190 |         _initAttrs : function(attrs, values, lazy) {
 | 
        
           |  |  | 1191 |             // ATTRS support for Node, which is not Base based
 | 
        
           |  |  | 1192 |             attrs = attrs || this.constructor.ATTRS;
 | 
        
           |  |  | 1193 |   | 
        
           |  |  | 1194 |             var Base = Y.Base,
 | 
        
           |  |  | 1195 |                 BaseCore = Y.BaseCore,
 | 
        
           |  |  | 1196 |                 baseInst = (Base && Y.instanceOf(this, Base)),
 | 
        
           |  |  | 1197 |                 baseCoreInst = (!baseInst && BaseCore && Y.instanceOf(this, BaseCore));
 | 
        
           |  |  | 1198 |   | 
        
           |  |  | 1199 |             if (attrs && !baseInst && !baseCoreInst) {
 | 
        
           |  |  | 1200 |                 this.addAttrs(Y.AttributeCore.protectAttrs(attrs), values, lazy);
 | 
        
           |  |  | 1201 |             }
 | 
        
           |  |  | 1202 |         }
 | 
        
           |  |  | 1203 |     };
 | 
        
           |  |  | 1204 |   | 
        
           |  |  | 1205 |     Y.AttributeCore = AttributeCore;
 | 
        
           |  |  | 1206 |   | 
        
           |  |  | 1207 |   | 
        
           |  |  | 1208 | }, '3.18.1', {"requires": ["oop"]});
 |