API Docs for: 3.13.0
Show:

File: cache/js/cache-offline.js

  1. /**
  2. * Provides a Cache subclass which uses HTML5 `localStorage` for persistence.
  3. *
  4. * @module cache
  5. * @submodule cache-offline
  6. */
  7.  
  8. /**
  9. * Extends Cache utility with offline functionality.
  10. * @class CacheOffline
  11. * @extends Cache
  12. * @constructor
  13. */
  14. function CacheOffline() {
  15. CacheOffline.superclass.constructor.apply(this, arguments);
  16. }
  17.  
  18. var localStorage = null,
  19. JSON = Y.JSON;
  20.  
  21. // Bug 2529572
  22. try {
  23. localStorage = Y.config.win.localStorage;
  24. }
  25. catch(e) {
  26. Y.log("Could not access localStorage.", "warn", "cache");
  27. }
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. //
  31. // CacheOffline events
  32. //
  33. /////////////////////////////////////////////////////////////////////////////
  34.  
  35. /**
  36. * @event error
  37. * @description Fired when an entry could not be added, most likely due to
  38. * exceeded browser quota.
  39. * <dl>
  40. * <dt>error (Object)</dt> <dd>The error object.</dd>
  41. * </dl>
  42. */
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. //
  46. // CacheOffline static
  47. //
  48. /////////////////////////////////////////////////////////////////////////////
  49. Y.mix(CacheOffline, {
  50. /**
  51. * Class name.
  52. *
  53. * @property NAME
  54. * @type String
  55. * @static
  56. * @final
  57. * @value "cacheOffline"
  58. */
  59. NAME: "cacheOffline",
  60.  
  61. ATTRS: {
  62. /////////////////////////////////////////////////////////////////////////////
  63. //
  64. // CacheOffline Attributes
  65. //
  66. /////////////////////////////////////////////////////////////////////////////
  67.  
  68. /**
  69. * @attribute sandbox
  70. * @description A string that must be passed in via the constructor.
  71. * This identifier is used to sandbox one cache instance's entries
  72. * from another. Calling the cache instance's flush and length methods
  73. * or get("entries") will apply to only these sandboxed entries.
  74. * @type String
  75. * @default "default"
  76. * @initOnly
  77. */
  78. sandbox: {
  79. value: "default",
  80. writeOnce: "initOnly"
  81. },
  82.  
  83. /**
  84. * @attribute expires
  85. * @description Absolute Date when data expires or
  86. * relative number of milliseconds. Zero disables expiration.
  87. * @type Date | Number
  88. * @default 86400000 (one day)
  89. */
  90. expires: {
  91. value: 86400000
  92. },
  93.  
  94. /**
  95. * @attribute max
  96. * @description Disabled.
  97. * @readOnly
  98. * @default null
  99. */
  100. max: {
  101. value: null,
  102. readOnly: true
  103. },
  104.  
  105. /**
  106. * @attribute uniqueKeys
  107. * @description Always true for CacheOffline.
  108. * @readOnly
  109. * @default true
  110. */
  111. uniqueKeys: {
  112. value: true,
  113. readOnly: true,
  114. setter: function() {
  115. return true;
  116. }
  117. }
  118. },
  119.  
  120. /**
  121. * Removes all items from all sandboxes. Useful if localStorage has
  122. * exceeded quota. Only supported on browsers that implement HTML 5
  123. * localStorage.
  124. *
  125. * @method flushAll
  126. * @static
  127. */
  128. flushAll: function() {
  129. var store = localStorage, key;
  130. if(store) {
  131. if(store.clear) {
  132. store.clear();
  133. }
  134. // FF2.x and FF3.0.x
  135. else {
  136. for (key in store) {
  137. if (store.hasOwnProperty(key)) {
  138. store.removeItem(key);
  139. delete store[key];
  140. }
  141. }
  142. }
  143. Y.log("All sandboxes of OfflineCache flushed", "info", "cache");
  144. }
  145. else {
  146. Y.log("Could not flush all OfflineCache sandboxes.", "warn", "cache");
  147. }
  148. }
  149. });
  150.  
  151. Y.extend(CacheOffline, Y.Cache, localStorage ? {
  152. /////////////////////////////////////////////////////////////////////////////
  153. //
  154. // Offline is supported
  155. //
  156. /////////////////////////////////////////////////////////////////////////////
  157.  
  158. /////////////////////////////////////////////////////////////////////////////
  159. //
  160. // CacheOffline protected methods
  161. //
  162. /////////////////////////////////////////////////////////////////////////////
  163. /**
  164. * Always return null.
  165. *
  166. * @method _setMax
  167. * @protected
  168. */
  169. _setMax: function(value) {
  170. return null;
  171. },
  172.  
  173. /**
  174. * Gets size.
  175. *
  176. * @method _getSize
  177. * @protected
  178. */
  179. _getSize: function() {
  180. var count = 0,
  181. i=0,
  182. l=localStorage.length;
  183. for(; i<l; ++i) {
  184. // Match sandbox id
  185. if(localStorage.key(i).indexOf(this.get("sandbox")) === 0) {
  186. count++;
  187. }
  188. }
  189. return count;
  190. },
  191.  
  192. /**
  193. * Gets all entries.
  194. *
  195. * @method _getEntries
  196. * @protected
  197. */
  198. _getEntries: function() {
  199. var entries = [],
  200. i=0,
  201. l=localStorage.length,
  202. sandbox = this.get("sandbox");
  203. for(; i<l; ++i) {
  204. // Match sandbox id
  205. if(localStorage.key(i).indexOf(sandbox) === 0) {
  206. entries[i] = JSON.parse(localStorage.key(i).substring(sandbox.length));
  207. }
  208. }
  209. return entries;
  210. },
  211.  
  212. /**
  213. * Adds entry to cache.
  214. *
  215. * @method _defAddFn
  216. * @param e {Event.Facade} Event Facade with the following properties:
  217. * <dl>
  218. * <dt>entry (Object)</dt> <dd>The cached entry.</dd>
  219. * </dl>
  220. * @protected
  221. */
  222. _defAddFn: function(e) {
  223. var entry = e.entry,
  224. request = entry.request,
  225. cached = entry.cached,
  226. expires = entry.expires;
  227.  
  228. // Convert Dates to msecs on the way into localStorage
  229. entry.cached = cached.getTime();
  230. entry.expires = expires ? expires.getTime() : expires;
  231.  
  232. try {
  233. localStorage.setItem(this.get("sandbox")+JSON.stringify({"request":request}), JSON.stringify(entry));
  234. Y.log("Cached offline entry: " + Y.dump(entry), "info", "cache");
  235. }
  236. catch(error) {
  237. this.fire("error", {error:error});
  238. Y.log("Could not cache offline entry: " + Y.dump(entry) +
  239. " due to error: " + Y.dump(error), "warn", "cache");
  240. }
  241. },
  242.  
  243. /**
  244. * Flushes cache.
  245. *
  246. * @method _defFlushFn
  247. * @param e {Event.Facade} Event Facade object.
  248. * @protected
  249. */
  250. _defFlushFn: function(e) {
  251. var key,
  252. i=localStorage.length-1;
  253. for(; i>-1; --i) {
  254. // Match sandbox id
  255. key = localStorage.key(i);
  256. if(key.indexOf(this.get("sandbox")) === 0) {
  257. localStorage.removeItem(key);
  258. }
  259. }
  260. },
  261.  
  262. /////////////////////////////////////////////////////////////////////////////
  263. //
  264. // CacheOffline public methods
  265. //
  266. /////////////////////////////////////////////////////////////////////////////
  267. /**
  268. * Adds a new entry to the cache of the format
  269. * {request:request, response:response, cached:cached, expires: expires}.
  270. *
  271. * @method add
  272. * @param request {Object} Request value must be a String or JSON.
  273. * @param response {Object} Response value must be a String or JSON.
  274. */
  275.  
  276. /**
  277. * Retrieves cached object for given request, if available.
  278. * Returns null if there is no cache match.
  279. *
  280. * @method retrieve
  281. * @param request {Object} Request object.
  282. * @return {Object} Cached object with the properties request, response,
  283. * and expires, or null.
  284. */
  285. retrieve: function(request) {
  286. this.fire("request", {request: request});
  287.  
  288. var entry, expires, sandboxedrequest;
  289.  
  290. try {
  291. sandboxedrequest = this.get("sandbox")+JSON.stringify({"request":request});
  292. try {
  293. entry = JSON.parse(localStorage.getItem(sandboxedrequest));
  294. }
  295. catch(e) {
  296. }
  297. }
  298. catch(e2) {
  299. }
  300.  
  301. if(entry) {
  302. // Convert msecs to Dates on the way out of localStorage
  303. entry.cached = new Date(entry.cached);
  304. expires = entry.expires;
  305. expires = !expires ? null : new Date(expires);
  306. entry.expires = expires;
  307.  
  308. if(this._isMatch(request, entry)) {
  309. this.fire("retrieve", {entry: entry});
  310. Y.log("Retrieved offlinecached response: " + Y.dump(entry) +
  311. " for request: " + Y.dump(request), "info", "cache");
  312. return entry;
  313. }
  314. }
  315. return null;
  316. }
  317. } :
  318. /////////////////////////////////////////////////////////////////////////////
  319. //
  320. // Offline is not supported
  321. //
  322. /////////////////////////////////////////////////////////////////////////////
  323. {
  324. /**
  325. * Always return null.
  326. *
  327. * @method _setMax
  328. * @protected
  329. */
  330. _setMax: function(value) {
  331. return null;
  332. }
  333. });
  334.  
  335.  
  336. Y.CacheOffline = CacheOffline;
  337.