Built motion from commit 7767ffc.|0.0.132
[motion.git] / public / bower_components / angular-local-storage / angular-local-storage.js
1 /**
2  * An Angular module that gives you access to the browsers local storage
3  * @version v0.2.6 - 2016-03-16
4  * @link https://github.com/grevory/angular-local-storage
5  * @author grevory <greg@gregpike.ca>
6  * @license MIT License, http://www.opensource.org/licenses/MIT
7  */
8 (function (window, angular) {
9 var isDefined = angular.isDefined,
10   isUndefined = angular.isUndefined,
11   isNumber = angular.isNumber,
12   isObject = angular.isObject,
13   isArray = angular.isArray,
14   extend = angular.extend,
15   toJson = angular.toJson;
16
17 angular
18   .module('LocalStorageModule', [])
19   .provider('localStorageService', function() {
20     // You should set a prefix to avoid overwriting any local storage variables from the rest of your app
21     // e.g. localStorageServiceProvider.setPrefix('yourAppName');
22     // With provider you can use config as this:
23     // myApp.config(function (localStorageServiceProvider) {
24     //    localStorageServiceProvider.prefix = 'yourAppName';
25     // });
26     this.prefix = 'ls';
27
28     // You could change web storage type localstorage or sessionStorage
29     this.storageType = 'localStorage';
30
31     // Cookie options (usually in case of fallback)
32     // expiry = Number of days before cookies expire // 0 = Does not expire
33     // path = The web path the cookie represents
34     this.cookie = {
35       expiry: 30,
36       path: '/'
37     };
38
39     // Send signals for each of the following actions?
40     this.notify = {
41       setItem: true,
42       removeItem: false
43     };
44
45     // Setter for the prefix
46     this.setPrefix = function(prefix) {
47       this.prefix = prefix;
48       return this;
49     };
50
51     // Setter for the storageType
52     this.setStorageType = function(storageType) {
53       this.storageType = storageType;
54       return this;
55     };
56
57     // Setter for cookie config
58     this.setStorageCookie = function(exp, path) {
59       this.cookie.expiry = exp;
60       this.cookie.path = path;
61       return this;
62     };
63
64     // Setter for cookie domain
65     this.setStorageCookieDomain = function(domain) {
66       this.cookie.domain = domain;
67       return this;
68     };
69
70     // Setter for notification config
71     // itemSet & itemRemove should be booleans
72     this.setNotify = function(itemSet, itemRemove) {
73       this.notify = {
74         setItem: itemSet,
75         removeItem: itemRemove
76       };
77       return this;
78     };
79
80     this.$get = ['$rootScope', '$window', '$document', '$parse', function($rootScope, $window, $document, $parse) {
81       var self = this;
82       var prefix = self.prefix;
83       var cookie = self.cookie;
84       var notify = self.notify;
85       var storageType = self.storageType;
86       var webStorage;
87
88       // When Angular's $document is not available
89       if (!$document) {
90         $document = document;
91       } else if ($document[0]) {
92         $document = $document[0];
93       }
94
95       // If there is a prefix set in the config lets use that with an appended period for readability
96       if (prefix.substr(-1) !== '.') {
97         prefix = !!prefix ? prefix + '.' : '';
98       }
99       var deriveQualifiedKey = function(key) {
100         return prefix + key;
101       };
102       // Checks the browser to see if local storage is supported
103       var browserSupportsLocalStorage = (function () {
104         try {
105           var supported = (storageType in $window && $window[storageType] !== null);
106
107           // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
108           // is available, but trying to call .setItem throws an exception.
109           //
110           // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
111           // that exceeded the quota."
112           var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
113           if (supported) {
114             webStorage = $window[storageType];
115             webStorage.setItem(key, '');
116             webStorage.removeItem(key);
117           }
118
119           return supported;
120         } catch (e) {
121           storageType = 'cookie';
122           $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
123           return false;
124         }
125       }());
126
127       // Directly adds a value to local storage
128       // If local storage is not available in the browser use cookies
129       // Example use: localStorageService.add('library','angular');
130       var addToLocalStorage = function (key, value) {
131         // Let's convert undefined values to null to get the value consistent
132         if (isUndefined(value)) {
133           value = null;
134         } else {
135           value = toJson(value);
136         }
137
138         // If this browser does not support local storage use cookies
139         if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
140           if (!browserSupportsLocalStorage) {
141             $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
142           }
143
144           if (notify.setItem) {
145             $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
146           }
147           return addToCookies(key, value);
148         }
149
150         try {
151           if (webStorage) {
152             webStorage.setItem(deriveQualifiedKey(key), value);
153           }
154           if (notify.setItem) {
155             $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
156           }
157         } catch (e) {
158           $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
159           return addToCookies(key, value);
160         }
161         return true;
162       };
163
164       // Directly get a value from local storage
165       // Example use: localStorageService.get('library'); // returns 'angular'
166       var getFromLocalStorage = function (key) {
167
168         if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
169           if (!browserSupportsLocalStorage) {
170             $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
171           }
172
173           return getFromCookies(key);
174         }
175
176         var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
177         // angular.toJson will convert null to 'null', so a proper conversion is needed
178         // FIXME not a perfect solution, since a valid 'null' string can't be stored
179         if (!item || item === 'null') {
180           return null;
181         }
182
183         try {
184           return JSON.parse(item);
185         } catch (e) {
186           return item;
187         }
188       };
189
190       // Remove an item from local storage
191       // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
192       var removeFromLocalStorage = function () {
193         var i, key;
194         for (i=0; i<arguments.length; i++) {
195           key = arguments[i];
196           if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
197             if (!browserSupportsLocalStorage) {
198               $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
199             }
200
201             if (notify.removeItem) {
202               $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
203             }
204             removeFromCookies(key);
205           }
206           else {
207             try {
208               webStorage.removeItem(deriveQualifiedKey(key));
209               if (notify.removeItem) {
210                 $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {
211                   key: key,
212                   storageType: self.storageType
213                 });
214               }
215             } catch (e) {
216               $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
217               removeFromCookies(key);
218             }
219           }
220         }
221       };
222
223       // Return array of keys for local storage
224       // Example use: var keys = localStorageService.keys()
225       var getKeysForLocalStorage = function () {
226
227         if (!browserSupportsLocalStorage) {
228           $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
229           return [];
230         }
231
232         var prefixLength = prefix.length;
233         var keys = [];
234         for (var key in webStorage) {
235           // Only return keys that are for this app
236           if (key.substr(0, prefixLength) === prefix) {
237             try {
238               keys.push(key.substr(prefixLength));
239             } catch (e) {
240               $rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
241               return [];
242             }
243           }
244         }
245         return keys;
246       };
247
248       // Remove all data for this app from local storage
249       // Also optionally takes a regular expression string and removes the matching key-value pairs
250       // Example use: localStorageService.clearAll();
251       // Should be used mostly for development purposes
252       var clearAllFromLocalStorage = function (regularExpression) {
253
254         // Setting both regular expressions independently
255         // Empty strings result in catchall RegExp
256         var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp();
257         var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp();
258
259         if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
260           if (!browserSupportsLocalStorage) {
261             $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
262           }
263           return clearAllFromCookies();
264         }
265
266         var prefixLength = prefix.length;
267
268         for (var key in webStorage) {
269           // Only remove items that are for this app and match the regular expression
270           if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) {
271             try {
272               removeFromLocalStorage(key.substr(prefixLength));
273             } catch (e) {
274               $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
275               return clearAllFromCookies();
276             }
277           }
278         }
279         return true;
280       };
281
282       // Checks the browser to see if cookies are supported
283       var browserSupportsCookies = (function() {
284         try {
285           return $window.navigator.cookieEnabled ||
286           ("cookie" in $document && ($document.cookie.length > 0 ||
287             ($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
288           } catch (e) {
289             $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
290             return false;
291           }
292         }());
293
294         // Directly adds a value to cookies
295         // Typically used as a fallback is local storage is not available in the browser
296         // Example use: localStorageService.cookie.add('library','angular');
297         var addToCookies = function (key, value, daysToExpiry) {
298
299           if (isUndefined(value)) {
300             return false;
301           } else if(isArray(value) || isObject(value)) {
302             value = toJson(value);
303           }
304
305           if (!browserSupportsCookies) {
306             $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
307             return false;
308           }
309
310           try {
311             var expiry = '',
312             expiryDate = new Date(),
313             cookieDomain = '';
314
315             if (value === null) {
316               // Mark that the cookie has expired one day ago
317               expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
318               expiry = "; expires=" + expiryDate.toGMTString();
319               value = '';
320             } else if (isNumber(daysToExpiry) && daysToExpiry !== 0) {
321               expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000));
322               expiry = "; expires=" + expiryDate.toGMTString();
323             } else if (cookie.expiry !== 0) {
324               expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
325               expiry = "; expires=" + expiryDate.toGMTString();
326             }
327             if (!!key) {
328               var cookiePath = "; path=" + cookie.path;
329               if(cookie.domain){
330                 cookieDomain = "; domain=" + cookie.domain;
331               }
332               $document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
333             }
334           } catch (e) {
335             $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
336             return false;
337           }
338           return true;
339         };
340
341         // Directly get a value from a cookie
342         // Example use: localStorageService.cookie.get('library'); // returns 'angular'
343         var getFromCookies = function (key) {
344           if (!browserSupportsCookies) {
345             $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
346             return false;
347           }
348
349           var cookies = $document.cookie && $document.cookie.split(';') || [];
350           for(var i=0; i < cookies.length; i++) {
351             var thisCookie = cookies[i];
352             while (thisCookie.charAt(0) === ' ') {
353               thisCookie = thisCookie.substring(1,thisCookie.length);
354             }
355             if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
356               var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length));
357               try {
358                 return JSON.parse(storedValues);
359               } catch(e) {
360                 return storedValues;
361               }
362             }
363           }
364           return null;
365         };
366
367         var removeFromCookies = function (key) {
368           addToCookies(key,null);
369         };
370
371         var clearAllFromCookies = function () {
372           var thisCookie = null, thisKey = null;
373           var prefixLength = prefix.length;
374           var cookies = $document.cookie.split(';');
375           for(var i = 0; i < cookies.length; i++) {
376             thisCookie = cookies[i];
377
378             while (thisCookie.charAt(0) === ' ') {
379               thisCookie = thisCookie.substring(1, thisCookie.length);
380             }
381
382             var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
383             removeFromCookies(key);
384           }
385         };
386
387         var getStorageType = function() {
388           return storageType;
389         };
390
391         // Add a listener on scope variable to save its changes to local storage
392         // Return a function which when called cancels binding
393         var bindToScope = function(scope, key, def, lsKey) {
394           lsKey = lsKey || key;
395           var value = getFromLocalStorage(lsKey);
396
397           if (value === null && isDefined(def)) {
398             value = def;
399           } else if (isObject(value) && isObject(def)) {
400             value = extend(value, def);
401           }
402
403           $parse(key).assign(scope, value);
404
405           return scope.$watch(key, function(newVal) {
406             addToLocalStorage(lsKey, newVal);
407           }, isObject(scope[key]));
408         };
409
410         // Return localStorageService.length
411         // ignore keys that not owned
412         var lengthOfLocalStorage = function() {
413           var count = 0;
414           var storage = $window[storageType];
415           for(var i = 0; i < storage.length; i++) {
416             if(storage.key(i).indexOf(prefix) === 0 ) {
417               count++;
418             }
419           }
420           return count;
421         };
422
423         return {
424           isSupported: browserSupportsLocalStorage,
425           getStorageType: getStorageType,
426           set: addToLocalStorage,
427           add: addToLocalStorage, //DEPRECATED
428           get: getFromLocalStorage,
429           keys: getKeysForLocalStorage,
430           remove: removeFromLocalStorage,
431           clearAll: clearAllFromLocalStorage,
432           bind: bindToScope,
433           deriveKey: deriveQualifiedKey,
434           length: lengthOfLocalStorage,
435           cookie: {
436             isSupported: browserSupportsCookies,
437             set: addToCookies,
438             add: addToCookies, //DEPRECATED
439             get: getFromCookies,
440             remove: removeFromCookies,
441             clearAll: clearAllFromCookies
442           }
443         };
444       }];
445   });
446 })(window, window.angular);