2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('cache-base', function (Y, NAME) {
11 * The Cache utility provides a common configurable interface for components to
12 * cache and retrieve data from a local JavaScript struct.
19 * Provides the base class for the YUI Cache utility.
21 * @submodule cache-base
24 isDate = Y.Lang.isDate,
27 * Base class for the YUI Cache utility.
33 Cache.superclass.constructor.apply(this, arguments);
36 /////////////////////////////////////////////////////////////////////////////
38 // Cache static properties
40 /////////////////////////////////////////////////////////////////////////////
55 /////////////////////////////////////////////////////////////////////////////
59 /////////////////////////////////////////////////////////////////////////////
63 * @description Maximum number of entries the Cache can hold.
64 * Set to 0 to turn off caching.
75 * @description Number of entries currently cached.
84 * @attribute uniqueKeys
85 * @description Validate uniqueness of stored keys. Default is false and
95 * @description Absolute Date when data expires or
96 * relative number of milliseconds. Zero disables expiration.
102 validator: function(v) {
103 return Y.Lang.isDate(v) || (Y.Lang.isNumber(v) && v >= 0);
109 * @description Cached entries.
114 getter: "_getEntries"
119 Y.extend(Cache, Y.Base, {
120 /////////////////////////////////////////////////////////////////////////////
122 // Cache private properties
124 /////////////////////////////////////////////////////////////////////////////
127 * Array of request/response objects indexed chronologically.
135 /////////////////////////////////////////////////////////////////////////////
137 // Cache private methods
139 /////////////////////////////////////////////////////////////////////////////
142 * @method initializer
143 * @description Internal init() handler.
144 * @param config {Object} Config object.
147 initializer: function(config) {
151 * @description Fired when an entry is added.
152 * @param e {Event.Facade} Event Facade with the following properties:
154 * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
156 * @preventable _defAddFn
158 this.publish("add", {defaultFn: this._defAddFn});
162 * @description Fired when the cache is flushed.
163 * @param e {Event.Facade} Event Facade object.
164 * @preventable _defFlushFn
166 this.publish("flush", {defaultFn: this._defFlushFn});
170 * @description Fired when an entry is requested from the cache.
171 * @param e {Event.Facade} Event Facade with the following properties:
173 * <dt>request (Object)</dt> <dd>The request object.</dd>
179 * @description Fired when an entry is retrieved from the cache.
180 * @param e {Event.Facade} Event Facade with the following properties:
182 * <dt>entry (Object)</dt> <dd>The retrieved entry.</dd>
186 // Initialize internal values
192 * @description Internal destroy() handler.
195 destructor: function() {
199 /////////////////////////////////////////////////////////////////////////////
201 // Cache protected methods
203 /////////////////////////////////////////////////////////////////////////////
211 _setMax: function(value) {
212 // If the cache is full, make room by removing stalest element (index=0)
213 var entries = this._entries;
216 while(entries.length > value) {
234 _getSize: function() {
235 return this._entries.length;
241 * @method _getEntries
244 _getEntries: function() {
245 return this._entries;
250 * Adds entry to cache.
253 * @param e {Event.Facade} Event Facade with the following properties:
255 * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
259 _defAddFn: function(e) {
260 var entries = this._entries,
262 max = this.get("max"),
265 // If uniqueKeys is true and item exists with this key, then remove it.
266 if (this.get("uniqueKeys")) {
267 pos = this._position(e.entry.request);
268 if (LANG.isValue(pos)) {
269 entries.splice(pos, 1);
273 // If the cache at or over capacity, make room by removing stalest
274 // element(s) starting at index-0.
275 while (max && entries.length >= max) {
279 // Add entry to cache in the newest position, at the end of the array
280 entries[entries.length] = entry;
286 * @method _defFlushFn
287 * @param e {Event.Facade} Event Facade object.
290 _defFlushFn: function(e) {
291 var entries = this._entries,
292 details = e.details[0],
295 //passed an item, flush only that
296 if(details && LANG.isValue(details.request)) {
297 pos = this._position(details.request);
299 if(LANG.isValue(pos)) {
300 entries.splice(pos,1);
304 //no item, flush everything
311 * Default overridable method compares current request with given cache entry.
312 * Returns true if current request matches the cached request, otherwise
313 * false. Implementers should override this method to customize the
314 * cache-matching algorithm.
317 * @param request {Object} Request object.
318 * @param entry {Object} Cached entry.
319 * @return {Boolean} True if current request matches given cached request, false otherwise.
322 _isMatch: function(request, entry) {
323 if(!entry.expires || new Date() < entry.expires) {
324 return (request === entry.request);
330 * Returns position of a request in the entries array, otherwise null.
333 * @param request {Object} Request object.
334 * @return {Number} Array position if found, null otherwise.
337 _position: function(request) {
338 // If cache is enabled...
339 var entries = this._entries,
340 length = entries.length,
343 if((this.get("max") === null) || this.get("max") > 0) {
344 // Loop through each cached entry starting from the newest
346 // Execute matching function
347 if(this._isMatch(request, entries[i])) {
356 /////////////////////////////////////////////////////////////////////////////
358 // Cache public methods
360 /////////////////////////////////////////////////////////////////////////////
363 * Adds a new entry to the cache of the format
364 * {request:request, response:response, cached:cached, expires:expires}.
365 * If cache is full, evicts the stalest entry before adding the new one.
368 * @param request {Object} Request value.
369 * @param response {Object} Response value.
371 add: function(request, response) {
372 var expires = this.get("expires");
373 if(this.get("initialized") && ((this.get("max") === null) || this.get("max") > 0) &&
374 (LANG.isValue(request) || LANG.isNull(request) || LANG.isUndefined(request))) {
375 this.fire("add", {entry: {
379 expires: isDate(expires) ? expires :
380 (expires ? new Date(new Date().getTime() + this.get("expires")) : null)
392 flush: function(request) {
393 this.fire("flush", { request: (LANG.isValue(request) ? request : null) });
397 * Retrieves cached object for given request, if available, and refreshes
398 * entry in the cache. Returns null if there is no cache match.
401 * @param request {Object} Request object.
402 * @return {Object} Cached object with the properties request and response, or null.
404 retrieve: function(request) {
405 // If cache is enabled...
406 var entries = this._entries,
407 length = entries.length,
411 if((length > 0) && ((this.get("max") === null) || (this.get("max") > 0))) {
412 this.fire("request", {request: request});
414 pos = this._position(request);
416 if(LANG.isValue(pos)) {
417 entry = entries[pos];
419 this.fire("retrieve", {entry: entry});
421 // Refresh the position of the cache hit
423 // Remove element from its original location
424 entries.splice(pos,1);
426 entries[entries.length] = entry;
439 }, '3.13.0', {"requires": ["base"]});