PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/ngStorage/0.3.9/ngStorage.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 212 lines | 137 code | 41 blank | 34 comment | 28 complexity | 9baee265643e37f301024c49df41822d MD5 | raw file
  1. (function (root, factory) {
  2. 'use strict';
  3. if (typeof define === 'function' && define.amd) {
  4. define(['angular'], factory);
  5. } else if (typeof exports === 'object') {
  6. module.exports = factory(require('angular'));
  7. } else {
  8. // Browser globals (root is window), we don't register it.
  9. factory(root.angular);
  10. }
  11. }(this , function (angular) {
  12. 'use strict';
  13. // RequireJS does not pass in Angular to us (will be undefined).
  14. // Fallback to window which should mostly be there.
  15. angular = (angular && angular.module ) ? angular : window.angular;
  16. /**
  17. * @ngdoc overview
  18. * @name ngStorage
  19. */
  20. return angular.module('ngStorage', [])
  21. /**
  22. * @ngdoc object
  23. * @name ngStorage.$localStorage
  24. * @requires $rootScope
  25. * @requires $window
  26. */
  27. .provider('$localStorage', _storageProvider('localStorage'))
  28. /**
  29. * @ngdoc object
  30. * @name ngStorage.$sessionStorage
  31. * @requires $rootScope
  32. * @requires $window
  33. */
  34. .provider('$sessionStorage', _storageProvider('sessionStorage'));
  35. function _storageProvider(storageType) {
  36. return function () {
  37. var storageKeyPrefix = 'ngStorage-';
  38. this.setKeyPrefix = function (prefix) {
  39. if (typeof prefix !== 'string') {
  40. throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setKeyPrefix() expects a String.');
  41. }
  42. storageKeyPrefix = prefix;
  43. };
  44. var serializer = angular.toJson;
  45. var deserializer = angular.fromJson;
  46. this.setSerializer = function (s) {
  47. if (typeof s !== 'function') {
  48. throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setSerializer expects a function.');
  49. }
  50. serializer = s;
  51. };
  52. this.setDeserializer = function (d) {
  53. if (typeof d !== 'function') {
  54. throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setDeserializer expects a function.');
  55. }
  56. deserializer = d;
  57. };
  58. // Note: This is not very elegant at all.
  59. this.get = function (key) {
  60. return deserializer(window[storageType].getItem(storageKeyPrefix + key));
  61. };
  62. // Note: This is not very elegant at all.
  63. this.set = function (key, value) {
  64. return window[storageType].setItem(storageKeyPrefix + key, serializer(value));
  65. };
  66. this.$get = [
  67. '$rootScope',
  68. '$window',
  69. '$log',
  70. '$timeout',
  71. function(
  72. $rootScope,
  73. $window,
  74. $log,
  75. $timeout
  76. ){
  77. function isStorageSupported(storageType) {
  78. // Some installations of IE, for an unknown reason, throw "SCRIPT5: Error: Access is denied"
  79. // when accessing window.localStorage. This happens before you try to do anything with it. Catch
  80. // that error and allow execution to continue.
  81. // fix 'SecurityError: DOM Exception 18' exception in Desktop Safari, Mobile Safari
  82. // when "Block cookies": "Always block" is turned on
  83. var supported;
  84. try {
  85. supported = $window[storageType];
  86. }
  87. catch (err) {
  88. supported = false;
  89. }
  90. // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
  91. // is available, but trying to call .setItem throws an exception below:
  92. // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."
  93. if (supported && storageType === 'localStorage') {
  94. var key = '__' + Math.round(Math.random() * 1e7);
  95. try {
  96. localStorage.setItem(key, key);
  97. localStorage.removeItem(key);
  98. }
  99. catch (err) {
  100. supported = false;
  101. }
  102. }
  103. return supported;
  104. }
  105. // The magic number 10 is used which only works for some keyPrefixes...
  106. // See https://github.com/gsklee/ngStorage/issues/137
  107. var prefixLength = storageKeyPrefix.length;
  108. // #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app
  109. var webStorage = isStorageSupported(storageType) || ($log.warn('This browser does not support Web Storage!'), {setItem: angular.noop, getItem: angular.noop}),
  110. $storage = {
  111. $default: function(items) {
  112. for (var k in items) {
  113. angular.isDefined($storage[k]) || ($storage[k] = items[k]);
  114. }
  115. $storage.$sync();
  116. return $storage;
  117. },
  118. $reset: function(items) {
  119. for (var k in $storage) {
  120. '$' === k[0] || (delete $storage[k] && webStorage.removeItem(storageKeyPrefix + k));
  121. }
  122. return $storage.$default(items);
  123. },
  124. $sync: function () {
  125. for (var i = 0, l = webStorage.length, k; i < l; i++) {
  126. // #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty)
  127. (k = webStorage.key(i)) && storageKeyPrefix === k.slice(0, prefixLength) && ($storage[k.slice(prefixLength)] = deserializer(webStorage.getItem(k)));
  128. }
  129. },
  130. $apply: function() {
  131. var temp$storage;
  132. _debounce = null;
  133. if (!angular.equals($storage, _last$storage)) {
  134. temp$storage = angular.copy(_last$storage);
  135. angular.forEach($storage, function(v, k) {
  136. if (angular.isDefined(v) && '$' !== k[0]) {
  137. webStorage.setItem(storageKeyPrefix + k, serializer(v))
  138. delete temp$storage[k];
  139. }
  140. });
  141. for (var k in temp$storage) {
  142. webStorage.removeItem(storageKeyPrefix + k);
  143. }
  144. _last$storage = angular.copy($storage);
  145. }
  146. },
  147. },
  148. _last$storage,
  149. _debounce;
  150. $storage.$sync();
  151. _last$storage = angular.copy($storage);
  152. $rootScope.$watch(function() {
  153. _debounce || (_debounce = $timeout($storage.$apply, 100, false));
  154. });
  155. // #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent`
  156. $window.addEventListener && $window.addEventListener('storage', function(event) {
  157. if (storageKeyPrefix === event.key.slice(0, prefixLength)) {
  158. event.newValue ? $storage[event.key.slice(prefixLength)] = deserializer(event.newValue) : delete $storage[event.key.slice(prefixLength)];
  159. _last$storage = angular.copy($storage);
  160. $rootScope.$apply();
  161. }
  162. });
  163. $window.addEventListener && $window.addEventListener('beforeunload', function() {
  164. $storage.$apply();
  165. });
  166. return $storage;
  167. }
  168. ];
  169. };
  170. }
  171. }));