API Docs for: 3.17.2
Show:

File: yui/js/yui-core.js

  1. /**
  2. The YUI module contains the components required for building the YUI seed file.
  3. This includes the script loading mechanism, a simple queue, and the core
  4. utilities for the library.
  5.  
  6. @module yui
  7. @submodule yui-base
  8. **/
  9.  
  10. var CACHED_DELIMITER = '__',
  11.  
  12. hasOwn = Object.prototype.hasOwnProperty,
  13. isObject = Y.Lang.isObject;
  14.  
  15. /**
  16. Returns a wrapper for a function which caches the return value of that function,
  17. keyed off of the combined string representation of the argument values provided
  18. when the wrapper is called.
  19.  
  20. Calling this function again with the same arguments will return the cached value
  21. rather than executing the wrapped function.
  22.  
  23. Note that since the cache is keyed off of the string representation of arguments
  24. passed to the wrapper function, arguments that aren't strings and don't provide
  25. a meaningful `toString()` method may result in unexpected caching behavior. For
  26. example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
  27. string `[object Object]` when used as a cache key.
  28.  
  29. @method cached
  30. @param {Function} source The function to memoize.
  31. @param {Object} [cache={}] Object in which to store cached values. You may seed
  32. this object with pre-existing cached values if desired.
  33. @param {any} [refetch] If supplied, this value is compared with the cached value
  34. using a `==` comparison. If the values are equal, the wrapped function is
  35. executed again even though a cached value exists.
  36. @return {Function} Wrapped function.
  37. @for YUI
  38. **/
  39. Y.cached = function (source, cache, refetch) {
  40. /*jshint expr: true*/
  41. cache || (cache = {});
  42.  
  43. return function (arg) {
  44. var key = arguments.length > 1 ?
  45. Array.prototype.join.call(arguments, CACHED_DELIMITER) :
  46. String(arg);
  47.  
  48. /*jshint eqeqeq: false*/
  49. if (!(key in cache) || (refetch && cache[key] == refetch)) {
  50. cache[key] = source.apply(source, arguments);
  51. }
  52.  
  53. return cache[key];
  54. };
  55. };
  56.  
  57. /**
  58. Returns the `location` object from the window/frame in which this YUI instance
  59. operates, or `undefined` when executing in a non-browser environment
  60. (e.g. Node.js).
  61.  
  62. It is _not_ recommended to hold references to the `window.location` object
  63. outside of the scope of a function in which its properties are being accessed or
  64. its methods are being called. This is because of a nasty bug/issue that exists
  65. in both Safari and MobileSafari browsers:
  66. [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
  67.  
  68. @method getLocation
  69. @return {location} The `location` object from the window/frame in which this YUI
  70. instance operates.
  71. @since 3.5.0
  72. **/
  73. Y.getLocation = function () {
  74. // It is safer to look this up every time because yui-base is attached to a
  75. // YUI instance before a user's config is applied; i.e. `Y.config.win` does
  76. // not point the correct window object when this file is loaded.
  77. var win = Y.config.win;
  78.  
  79. // It is not safe to hold a reference to the `location` object outside the
  80. // scope in which it is being used. The WebKit engine used in Safari and
  81. // MobileSafari will "disconnect" the `location` object from the `window`
  82. // when a page is restored from back/forward history cache.
  83. return win && win.location;
  84. };
  85.  
  86. /**
  87. Returns a new object containing all of the properties of all the supplied
  88. objects. The properties from later objects will overwrite those in earlier
  89. objects.
  90.  
  91. Passing in a single object will create a shallow copy of it. For a deep copy,
  92. use `clone()`.
  93.  
  94. @method merge
  95. @param {Object} objects* One or more objects to merge.
  96. @return {Object} A new merged object.
  97. **/
  98. Y.merge = function () {
  99. var i = 0,
  100. len = arguments.length,
  101. result = {},
  102. key,
  103. obj;
  104.  
  105. for (; i < len; ++i) {
  106. obj = arguments[i];
  107.  
  108. for (key in obj) {
  109. if (hasOwn.call(obj, key)) {
  110. result[key] = obj[key];
  111. }
  112. }
  113. }
  114.  
  115. return result;
  116. };
  117.  
  118. /**
  119. Mixes _supplier_'s properties into _receiver_.
  120.  
  121. Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
  122. shadowed unless the _overwrite_ parameter is `true`, and will not be merged
  123. unless the _merge_ parameter is `true`.
  124.  
  125. In the default mode (0), only properties the supplier owns are copied (prototype
  126. properties are not copied). The following copying modes are available:
  127.  
  128. * `0`: _Default_. Object to object.
  129. * `1`: Prototype to prototype.
  130. * `2`: Prototype to prototype and object to object.
  131. * `3`: Prototype to object.
  132. * `4`: Object to prototype.
  133.  
  134. @method mix
  135. @param {Function|Object} receiver The object or function to receive the mixed
  136. properties.
  137. @param {Function|Object} supplier The object or function supplying the
  138. properties to be mixed.
  139. @param {Boolean} [overwrite=false] If `true`, properties that already exist
  140. on the receiver will be overwritten with properties from the supplier.
  141. @param {String[]} [whitelist] An array of property names to copy. If
  142. specified, only the whitelisted properties will be copied, and all others
  143. will be ignored.
  144. @param {Number} [mode=0] Mix mode to use. See above for available modes.
  145. @param {Boolean} [merge=false] If `true`, objects and arrays that already
  146. exist on the receiver will have the corresponding object/array from the
  147. supplier merged into them, rather than being skipped or overwritten. When
  148. both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
  149. @return {Function|Object|YUI} The receiver, or the YUI instance if the
  150. specified receiver is falsy.
  151. **/
  152. Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
  153. var alwaysOverwrite, exists, from, i, key, len, to;
  154.  
  155. // If no supplier is given, we return the receiver. If no receiver is given,
  156. // we return Y. Returning Y doesn't make much sense to me, but it's
  157. // grandfathered in for backcompat reasons.
  158. if (!receiver || !supplier) {
  159. return receiver || Y;
  160. }
  161.  
  162. if (mode) {
  163. // In mode 2 (prototype to prototype and object to object), we recurse
  164. // once to do the proto to proto mix. The object to object mix will be
  165. // handled later on.
  166. if (mode === 2) {
  167. Y.mix(receiver.prototype, supplier.prototype, overwrite,
  168. whitelist, 0, merge);
  169. }
  170.  
  171. // Depending on which mode is specified, we may be copying from or to
  172. // the prototypes of the supplier and receiver.
  173. from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
  174. to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
  175.  
  176. // If either the supplier or receiver doesn't actually have a
  177. // prototype property, then we could end up with an undefined `from`
  178. // or `to`. If that happens, we abort and return the receiver.
  179. if (!from || !to) {
  180. return receiver;
  181. }
  182. } else {
  183. from = supplier;
  184. to = receiver;
  185. }
  186.  
  187. // If `overwrite` is truthy and `merge` is falsy, then we can skip a
  188. // property existence check on each iteration and save some time.
  189. alwaysOverwrite = overwrite && !merge;
  190.  
  191. if (whitelist) {
  192. for (i = 0, len = whitelist.length; i < len; ++i) {
  193. key = whitelist[i];
  194.  
  195. // We call `Object.prototype.hasOwnProperty` instead of calling
  196. // `hasOwnProperty` on the object itself, since the object's
  197. // `hasOwnProperty` method may have been overridden or removed.
  198. // Also, some native objects don't implement a `hasOwnProperty`
  199. // method.
  200. if (!hasOwn.call(from, key)) {
  201. continue;
  202. }
  203.  
  204. // The `key in to` check here is (sadly) intentional for backwards
  205. // compatibility reasons. It prevents undesired shadowing of
  206. // prototype members on `to`.
  207. exists = alwaysOverwrite ? false : key in to;
  208.  
  209. if (merge && exists && isObject(to[key], true)
  210. && isObject(from[key], true)) {
  211. // If we're in merge mode, and the key is present on both
  212. // objects, and the value on both objects is either an object or
  213. // an array (but not a function), then we recurse to merge the
  214. // `from` value into the `to` value instead of overwriting it.
  215. //
  216. // Note: It's intentional that the whitelist isn't passed to the
  217. // recursive call here. This is legacy behavior that lots of
  218. // code still depends on.
  219. Y.mix(to[key], from[key], overwrite, null, 0, merge);
  220. } else if (overwrite || !exists) {
  221. // We're not in merge mode, so we'll only copy the `from` value
  222. // to the `to` value if we're in overwrite mode or if the
  223. // current key doesn't exist on the `to` object.
  224. to[key] = from[key];
  225. }
  226. }
  227. } else {
  228. for (key in from) {
  229. // The code duplication here is for runtime performance reasons.
  230. // Combining whitelist and non-whitelist operations into a single
  231. // loop or breaking the shared logic out into a function both result
  232. // in worse performance, and Y.mix is critical enough that the byte
  233. // tradeoff is worth it.
  234. if (!hasOwn.call(from, key)) {
  235. continue;
  236. }
  237.  
  238. // The `key in to` check here is (sadly) intentional for backwards
  239. // compatibility reasons. It prevents undesired shadowing of
  240. // prototype members on `to`.
  241. exists = alwaysOverwrite ? false : key in to;
  242.  
  243. if (merge && exists && isObject(to[key], true)
  244. && isObject(from[key], true)) {
  245. Y.mix(to[key], from[key], overwrite, null, 0, merge);
  246. } else if (overwrite || !exists) {
  247. to[key] = from[key];
  248. }
  249. }
  250.  
  251. // If this is an IE browser with the JScript enumeration bug, force
  252. // enumeration of the buggy properties by making a recursive call with
  253. // the buggy properties as the whitelist.
  254. if (Y.Object._hasEnumBug) {
  255. Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
  256. }
  257. }
  258.  
  259. return receiver;
  260. };
  261.