1YUI.add('oop', function (Y, NAME) { 2 3/** 4Adds object inheritance and manipulation utilities to the YUI instance. This 5module is required by most YUI components. 6 7@module oop 8**/ 9 10var L = Y.Lang, 11 A = Y.Array, 12 OP = Object.prototype, 13 CLONE_MARKER = '_~yuim~_', 14 15 hasOwn = OP.hasOwnProperty, 16 toString = OP.toString; 17 18function dispatch(o, f, c, proto, action) { 19 if (o && o[action] && o !== Y) { 20 return o[action].call(o, f, c); 21 } else { 22 switch (A.test(o)) { 23 case 1: 24 return A[action](o, f, c); 25 case 2: 26 return A[action](Y.Array(o, 0, true), f, c); 27 default: 28 return Y.Object[action](o, f, c, proto); 29 } 30 } 31} 32 33/** 34Augments the _receiver_ with prototype properties from the _supplier_. The 35receiver may be a constructor function or an object. The supplier must be a 36constructor function. 37 38If the _receiver_ is an object, then the _supplier_ constructor will be called 39immediately after _receiver_ is augmented, with _receiver_ as the `this` object. 40 41If the _receiver_ is a constructor function, then all prototype methods of 42_supplier_ that are copied to _receiver_ will be sequestered, and the 43_supplier_ constructor will not be called immediately. The first time any 44sequestered method is called on the _receiver_'s prototype, all sequestered 45methods will be immediately copied to the _receiver_'s prototype, the 46_supplier_'s constructor will be executed, and finally the newly unsequestered 47method that was called will be executed. 48 49This sequestering logic sounds like a bunch of complicated voodoo, but it makes 50it cheap to perform frequent augmentation by ensuring that suppliers'
51constructors are only called if a supplied method is actually used. If none of 52the supplied methods is ever used, then there's no need to take the performance 53hit of calling the _supplier_'s constructor. 54 55@method augment 56@param {Function|Object} receiver Object or function to be augmented. 57@param {Function} supplier Function that supplies the prototype properties with 58 which to augment the _receiver_. 59@param {Boolean} [overwrite=false] If `true`, properties already on the receiver 60 will be overwritten if found on the supplier's prototype. 61@param {String[]} [whitelist] An array of property names. If specified, 62 only the whitelisted prototype properties will be applied to the receiver, and 63 all others will be ignored. 64@param {Array|any} [args] Argument or array of arguments to pass to the 65 supplier's constructor when initializing. 66@return {Function} Augmented object. 67@for YUI 68**/ 69Y.augment = function (receiver, supplier, overwrite, whitelist, args) { 70 var rProto = receiver.prototype, 71 sequester = rProto && supplier, 72 sProto = supplier.prototype, 73 to = rProto || receiver, 74 75 copy, 76 newPrototype, 77 replacements, 78 sequestered, 79 unsequester; 80 81 args = args ? Y.Array(args) : []; 82 83 if (sequester) { 84 newPrototype = {}; 85 replacements = {}; 86 sequestered = {}; 87 88 copy = function (value, key) { 89 if (overwrite || !(key in rProto)) { 90 if (toString.call(value) === '[object Function]') { 91 sequestered[key] = value; 92 93 newPrototype[key] = replacements[key] = function () { 94 return unsequester(this, value, arguments); 95 }; 96 } else { 97 newPrototype[key] = value; 98 } 99 } 100 }; 101 102 unsequester = function (instance, fn, fnArgs) { 103 // Unsequester all sequestered functions. 104 for (var key in sequestered) { 105 if (hasOwn.call(sequestered, key) 106 && instance[key] === replacements[key]) { 107 108 instance[key] = sequestered[key]; 109 } 110 } 111 112 // Execute the supplier constructor. 113 supplier.apply(instance, args); 114 115 // Finally, execute the original sequestered function. 116 return fn.apply(instance, fnArgs); 117 }; 118 119 if (whitelist) { 120 Y.Array.each(whitelist, function (name) { 121 if (name in sProto) { 122 copy(sProto[name], name); 123 } 124 }); 125 } else { 126 Y.Object.each(sProto, copy, null, true); 127 } 128 } 129 130 Y.mix(to, newPrototype || sProto, overwrite, whitelist); 131 132 if (!sequester) { 133 supplier.apply(to, args); 134 } 135 136 return receiver; 137}; 138 139/** 140 * Copies object properties from the supplier to the receiver. If the target has 141 * the property, and the property is an object, the target object will be 142 * augmented with the supplier's value. 143 * 144 * @method aggregate 145 * @param {Object} receiver Object to receive the augmentation. 146 * @param {Object} supplier Object that supplies the properties with which to 147 * augment the receiver. 148 * @param {Boolean} [overwrite=false] If `true`, properties already on the receiver 149 * will be overwritten if found on the supplier. 150 * @param {String[]} [whitelist] Whitelist. If supplied, only properties in this 151 * list will be applied to the receiver. 152 * @return {Object} Augmented object. 153 */ 154Y.aggregate = function(r, s, ov, wl) { 155 return Y.mix(r, s, ov, wl, 0, true); 156}; 157 158/** 159 * Utility to set up the prototype, constructor and superclass properties to 160 * support an inheritance strategy that can chain constructors and methods. 161 * Static members will not be inherited. 162 * 163 * @method extend 164 * @param {function} r the object to modify. 165 * @param {function} s the object to inherit. 166 * @param {object} px prototype properties to add/override. 167 * @param {object} sx static properties to add/override. 168 * @return {object} the extended object. 169 */ 170Y.extend = function(r, s, px, sx) { 171 if (!s || !r) { 172 Y.error('extend failed, verify dependencies'); 173 } 174 175 var sp = s.prototype, rp = Y.Object(sp); 176 r.prototype = rp; 177 178 rp.constructor = r; 179 r.superclass = sp; 180 181 // assign constructor property 182 if (s != Object && sp.constructor == OP.constructor) { 183 sp.constructor = s; 184 } 185 186 // add prototype overrides 187 if (px) { 188 Y.mix(rp, px, true); 189 } 190 191 // add object overrides 192 if (sx) { 193 Y.mix(r, sx, true); 194 } 195 196 return r; 197}; 198 199/** 200 * Executes the supplied function for each item in 201 * a collection. Supports arrays, objects, and 202 * NodeLists 203 * @method each 204 * @param {object} o the object to iterate. 205 * @param {function} f the function to execute. This function 206 * receives the value, key, and object as parameters. 207 * @param {object} c the execution context for the function. 208 * @param {boolean} proto if true, prototype properties are 209 * iterated on objects. 210 * @return {YUI} the YUI instance. 211 */ 212Y.each = function(o, f, c, proto) {
213 return dispatch(o, f, c, proto, 'each'); 214}; 215 216/** 217 * Executes the supplied function for each item in 218 * a collection. The operation stops if the function 219 * returns true. Supports arrays, objects, and 220 * NodeLists. 221 * @method some 222 * @param {object} o the object to iterate. 223 * @param {function} f the function to execute. This function 224 * receives the value, key, and object as parameters. 225 * @param {object} c the execution context for the function. 226 * @param {boolean} proto if true, prototype properties are 227 * iterated on objects. 228 * @return {boolean} true if the function ever returns true, 229 * false otherwise. 230 */ 231Y.some = function(o, f, c, proto) { 232 return dispatch(o, f, c, proto, 'some'); 233}; 234 235/** 236Deep object/array copy. Function clones are actually wrappers around the 237original function. Array-like objects are treated as arrays. Primitives are 238returned untouched. Optionally, a function can be provided to handle other data 239types, filter keys, validate values, etc. 240 241**Note:** Cloning a non-trivial object is a reasonably heavy operation, due to 242the need to recursively iterate down non-primitive properties. Clone should be 243used only when a deep clone down to leaf level properties is explicitly 244required. This method will also 245 246In many cases (for example, when trying to isolate objects used as hashes for 247configuration properties), a shallow copy, using `Y.merge()` is normally 248sufficient. If more than one level of isolation is required, `Y.merge()` can be 249used selectively at each level which needs to be isolated from the original 250without going all the way to leaf properties. 251 252@method clone 253@param {object} o what to clone. 254@param {boolean} safe if true, objects will not have prototype items from the 255 source. If false, they will. In this case, the original is initially 256 protected, but the clone is not completely immune from changes to the source 257 object prototype. Also, cloned prototype items that are deleted from the 258 clone will result in the value of the source prototype being exposed. If 259 operating on a non-safe clone, items should be nulled out rather than 260 deleted. 261@param {function} f optional function to apply to each item in a collection; it 262 will be executed prior to applying the value to the new object. 263 Return false to prevent the copy. 264@param {object} c optional execution context for f. 265@param {object} owner Owner object passed when clone is iterating an object. 266 Used to set up context for cloned functions. 267@param {object} cloned hash of previously cloned objects to avoid multiple 268 clones. 269@return {Array|Object} the cloned object. 270**/ 271Y.clone = function(o, safe, f, c, owner, cloned) { 272 var o2, marked, stamp; 273 274 // Does not attempt to clone: 275 // 276 // * Non-typeof-object values, "primitive" values don't need cloning. 277 // 278 // * YUI instances, cloning complex object like YUI instances is not 279 // advised, this is like cloning the world. 280 // 281 // * DOM nodes (#2528250), common host objects like DOM nodes cannot be 282 // "subclassed" in Firefox and old versions of IE. Trying to use 283 // `Object.create()` or `Y.extend()` on a DOM node will throw an error in 284 // these browsers. 285 // 286 // Instad, the passed-in `o` will be return as-is when it matches one of the 287 // above criteria. 288 if (!L.isObject(o) || 289 Y.instanceOf(o, YUI) || 290 (o.addEventListener || o.attachEvent)) { 291 292 return o; 293 } 294 295 marked = cloned || {}; 296 297 switch (L.type(o)) { 298 case 'date': 299 return new Date(o); 300 case 'regexp': 301 // if we do this we need to set the flags too 302 // return new RegExp(o.source); 303 return o; 304 case 'function': 305 // o2 = Y.bind(o, owner); 306 // break; 307 return o; 308 case 'array': 309 o2 = []; 310 break; 311 default: 312 313 // #2528250 only one clone of a given object should be created. 314 if (o[CLONE_MARKER]) { 315 return marked[o[CLONE_MARKER]]; 316 } 317 318 stamp = Y.guid(); 319 320 o2 = (safe) ? {} : Y.Object(o); 321 322 o[CLONE_MARKER] = stamp; 323 marked[stamp] = o; 324 } 325 326 Y.each(o, function(v, k) { 327 if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) { 328 if (k !== CLONE_MARKER) { 329 if (k == 'prototype') { 330 // skip the prototype 331 // } else if (o[k] === o) { 332 // this[k] = this; 333 } else { 334 this[k] = 335 Y.clone(v, safe, f, c, owner || o, marked); 336 } 337 } 338 } 339 }, o2); 340 341 if (!cloned) { 342 Y.Object.each(marked, function(v, k) { 343 if (v[CLONE_MARKER]) { 344 try { 345 delete v[CLONE_MARKER]; 346 } catch (e) { 347 v[CLONE_MARKER] = null; 348 } 349 } 350 }, this); 351 marked = null; 352 } 353 354 return o2; 355}; 356 357/** 358 * Returns a function that will execute the supplied function in the 359 * supplied object's context, optionally adding any additional 360 * supplied parameters to the beginning of the arguments collection the 361 * supplied to the function. 362 * 363 * @method bind 364 * @param {Function|String} f the function to bind, or a function name 365 * to execute on the context object. 366 * @param {object} c the execution context. 367 * @param {any} args* 0..n arguments to include before the arguments the 368 * function is executed with. 369 * @return {function} the wrapped function. 370 */ 371Y.bind = function(f, c) { 372 var xargs = arguments.length > 2 ? 373 Y.Array(arguments, 2, true) : null; 374 return function() { 375 var fn = L.isString(f) ? c[f] : f, 376 args = (xargs) ? 377 xargs.concat(Y.Array(arguments, 0, true)) : arguments; 378 return fn.apply(c || fn, args); 379 }; 380}; 381 382/** 383 * Returns a function that will execute the supplied function in the 384 * supplied object's context, optionally adding any additional 385 * supplied parameters to the end of the arguments the function 386 * is executed with. 387 * 388 * @method rbind 389 * @param {Function|String} f the function to bind, or a function name 390 * to execute on the context object. 391 * @param {object} c the execution context. 392 * @param {any} args* 0..n arguments to append to the end of 393 * arguments collection supplied to the function. 394 * @return {function} the wrapped function. 395 */ 396Y.rbind = function(f, c) { 397 var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null; 398 return function() { 399 var fn = L.isString(f) ? c[f] : f, 400 args = (xargs) ? 401 Y.Array(arguments, 0, true).concat(xargs) : arguments; 402 return fn.apply(c || fn, args); 403 }; 404}; 405 406 407}, 'patched-v3.11.0', {"requires": ["yui-base"]});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.