This repository has been archived on 2020-10-11. You can view files and clone it, but cannot push or open issues or pull requests.
angular-local-storage/dist/angular-local-storage.js

450 lines
15 KiB
JavaScript
Raw Normal View History

2014-08-15 17:05:57 +00:00
/**
* An Angular module that gives you access to the browsers local storage
* @version v0.1.4 - 2014-10-30
2014-08-15 17:05:57 +00:00
* @link https://github.com/grevory/angular-local-storage
* @author grevory <greg@gregpike.ca>
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
(function ( window, angular, undefined ) {
2014-10-06 22:15:20 +00:00
/*jshint globalstrict:true*/
2014-08-15 17:05:57 +00:00
'use strict';
2014-10-06 22:15:20 +00:00
var isDefined = angular.isDefined,
isUndefined = angular.isUndefined,
isNumber = angular.isNumber,
isObject = angular.isObject,
isArray = angular.isArray,
extend = angular.extend,
toJson = angular.toJson,
fromJson = angular.fromJson;
// Test if string is only contains numbers
// e.g '1' => true, "'1'" => true
function isStringNumber(num) {
return /^-?\d+\.?\d*$/.test(num.replace(/["']/g, ''));
}
2014-08-15 17:05:57 +00:00
var angularLocalStorage = angular.module('LocalStorageModule', []);
angularLocalStorage.provider('localStorageService', function() {
// You should set a prefix to avoid overwriting any local storage variables from the rest of your app
// e.g. localStorageServiceProvider.setPrefix('youAppName');
// With provider you can use config as this:
// myApp.config(function (localStorageServiceProvider) {
// localStorageServiceProvider.prefix = 'yourAppName';
// });
this.prefix = 'ls';
// You could change web storage type localstorage or sessionStorage
this.storageType = 'localStorage';
// Cookie options (usually in case of fallback)
// expiry = Number of days before cookies expire // 0 = Does not expire
// path = The web path the cookie represents
this.cookie = {
expiry: 30,
path: '/'
};
// Send signals for each of the following actions?
this.notify = {
setItem: true,
removeItem: false
};
// Setter for the prefix
this.setPrefix = function(prefix) {
this.prefix = prefix;
};
// Setter for the storageType
this.setStorageType = function(storageType) {
this.storageType = storageType;
};
// Setter for cookie config
this.setStorageCookie = function(exp, path) {
this.cookie = {
expiry: exp,
path: path
};
};
// Setter for cookie domain
this.setStorageCookieDomain = function(domain) {
this.cookie.domain = domain;
};
// Setter for notification config
// itemSet & itemRemove should be booleans
this.setNotify = function(itemSet, itemRemove) {
this.notify = {
setItem: itemSet,
removeItem: itemRemove
};
};
2014-10-06 22:15:20 +00:00
this.$get = ['$rootScope', '$window', '$document', '$parse', function($rootScope, $window, $document, $parse) {
2014-08-15 17:05:57 +00:00
var self = this;
var prefix = self.prefix;
var cookie = self.cookie;
var notify = self.notify;
var storageType = self.storageType;
var webStorage;
// When Angular's $document is not available
if (!$document) {
$document = document;
} else if ($document[0]) {
$document = $document[0];
}
// If there is a prefix set in the config lets use that with an appended period for readability
if (prefix.substr(-1) !== '.') {
prefix = !!prefix ? prefix + '.' : '';
}
var deriveQualifiedKey = function(key) {
return prefix + key;
2014-10-06 22:15:20 +00:00
};
2014-08-15 17:05:57 +00:00
// Checks the browser to see if local storage is supported
var browserSupportsLocalStorage = (function () {
try {
var supported = (storageType in $window && $window[storageType] !== null);
// When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
// is available, but trying to call .setItem throws an exception.
//
// "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
// that exceeded the quota."
var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
if (supported) {
webStorage = $window[storageType];
webStorage.setItem(key, '');
webStorage.removeItem(key);
}
return supported;
} catch (e) {
storageType = 'cookie';
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
return false;
}
}());
// Directly adds a value to local storage
// If local storage is not available in the browser use cookies
// Example use: localStorageService.add('library','angular');
var addToLocalStorage = function (key, value) {
2014-10-06 22:15:20 +00:00
// Let's convert undefined values to null to get the value consistent
if (isUndefined(value)) {
value = null;
} else if (isObject(value) || isArray(value) || isNumber(+value || value)) {
value = toJson(value);
}
2014-08-15 17:05:57 +00:00
// If this browser does not support local storage use cookies
if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
2014-10-06 22:15:20 +00:00
if (!browserSupportsLocalStorage) {
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
}
2014-08-15 17:05:57 +00:00
if (notify.setItem) {
$rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
}
return addToCookies(key, value);
}
try {
2014-10-06 22:15:20 +00:00
if (isObject(value) || isArray(value)) {
value = toJson(value);
2014-08-15 17:05:57 +00:00
}
if (webStorage) {webStorage.setItem(deriveQualifiedKey(key), value)};
if (notify.setItem) {
$rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
}
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
return addToCookies(key, value);
}
return true;
};
// Directly get a value from local storage
// Example use: localStorageService.get('library'); // returns 'angular'
var getFromLocalStorage = function (key) {
if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
2014-10-06 22:15:20 +00:00
if (!browserSupportsLocalStorage) {
$rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
}
2014-08-15 17:05:57 +00:00
return getFromCookies(key);
}
var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
// angular.toJson will convert null to 'null', so a proper conversion is needed
// FIXME not a perfect solution, since a valid 'null' string can't be stored
if (!item || item === 'null') {
return null;
}
2014-10-06 22:15:20 +00:00
if (item.charAt(0) === "{" || item.charAt(0) === "[" || isStringNumber(item)) {
return fromJson(item);
2014-08-15 17:05:57 +00:00
}
return item;
};
// Remove an item from local storage
// Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
var removeFromLocalStorage = function (key) {
2014-10-06 22:15:20 +00:00
if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
if (!browserSupportsLocalStorage) {
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
}
2014-08-15 17:05:57 +00:00
if (notify.removeItem) {
$rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
}
return removeFromCookies(key);
}
try {
webStorage.removeItem(deriveQualifiedKey(key));
if (notify.removeItem) {
$rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: self.storageType});
}
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
return removeFromCookies(key);
}
return true;
};
// Return array of keys for local storage
// Example use: var keys = localStorageService.keys()
var getKeysForLocalStorage = function () {
if (!browserSupportsLocalStorage) {
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
return false;
}
var prefixLength = prefix.length;
var keys = [];
for (var key in webStorage) {
// Only return keys that are for this app
if (key.substr(0,prefixLength) === prefix) {
try {
keys.push(key.substr(prefixLength));
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
return [];
}
}
}
return keys;
};
// Remove all data for this app from local storage
// Also optionally takes a regular expression string and removes the matching key-value pairs
// Example use: localStorageService.clearAll();
// Should be used mostly for development purposes
var clearAllFromLocalStorage = function (regularExpression) {
regularExpression = regularExpression || "";
//accounting for the '.' in the prefix when creating a regex
var tempPrefix = prefix.slice(0, -1);
var testRegex = new RegExp(tempPrefix + '.' + regularExpression);
2014-10-06 22:15:20 +00:00
if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
if (!browserSupportsLocalStorage) {
$rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
}
2014-08-15 17:05:57 +00:00
return clearAllFromCookies();
}
var prefixLength = prefix.length;
for (var key in webStorage) {
// Only remove items that are for this app and match the regular expression
if (testRegex.test(key)) {
try {
removeFromLocalStorage(key.substr(prefixLength));
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
return clearAllFromCookies();
}
}
}
return true;
};
// Checks the browser to see if cookies are supported
var browserSupportsCookies = (function() {
2014-08-15 17:05:57 +00:00
try {
return $window.navigator.cookieEnabled ||
2014-08-15 17:05:57 +00:00
("cookie" in $document && ($document.cookie.length > 0 ||
($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
return false;
}
}());
2014-08-15 17:05:57 +00:00
// Directly adds a value to cookies
// Typically used as a fallback is local storage is not available in the browser
// Example use: localStorageService.cookie.add('library','angular');
var addToCookies = function (key, value) {
2014-10-06 22:15:20 +00:00
if (isUndefined(value)) {
2014-08-15 17:05:57 +00:00
return false;
2014-10-06 22:15:20 +00:00
} else if(isArray(value) || isObject(value)) {
value = toJson(value);
2014-08-15 17:05:57 +00:00
}
if (!browserSupportsCookies) {
2014-08-15 17:05:57 +00:00
$rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
return false;
}
try {
var expiry = '',
expiryDate = new Date(),
cookieDomain = '';
if (value === null) {
// Mark that the cookie has expired one day ago
expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
expiry = "; expires=" + expiryDate.toGMTString();
value = '';
} else if (cookie.expiry !== 0) {
expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
expiry = "; expires=" + expiryDate.toGMTString();
}
if (!!key) {
var cookiePath = "; path=" + cookie.path;
if(cookie.domain){
cookieDomain = "; domain=" + cookie.domain;
}
$document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
}
} catch (e) {
$rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
return false;
}
return true;
};
// Directly get a value from a cookie
// Example use: localStorageService.cookie.get('library'); // returns 'angular'
var getFromCookies = function (key) {
if (!browserSupportsCookies) {
2014-08-15 17:05:57 +00:00
$rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
return false;
}
var cookies = $document.cookie && $document.cookie.split(';') || [];
for(var i=0; i < cookies.length; i++) {
var thisCookie = cookies[i];
while (thisCookie.charAt(0) === ' ') {
thisCookie = thisCookie.substring(1,thisCookie.length);
}
if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
2014-10-06 22:15:20 +00:00
var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length))
try{
var obj = JSON.parse(storedValues);
return fromJson(obj)
}catch(e){
return storedValues
}
2014-08-15 17:05:57 +00:00
}
}
return null;
};
var removeFromCookies = function (key) {
addToCookies(key,null);
};
var clearAllFromCookies = function () {
var thisCookie = null, thisKey = null;
var prefixLength = prefix.length;
var cookies = $document.cookie.split(';');
for(var i = 0; i < cookies.length; i++) {
thisCookie = cookies[i];
while (thisCookie.charAt(0) === ' ') {
thisCookie = thisCookie.substring(1, thisCookie.length);
}
var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
removeFromCookies(key);
}
};
var getStorageType = function() {
return storageType;
};
2014-10-10 21:39:02 +00:00
// Add a listener on scope variable to save its changes to local storage
// Return a function which when called cancels binding
2014-10-13 22:36:11 +00:00
var bindToScope = function(scope, key, def, lsKey) {
lsKey = lsKey || key;
2014-10-06 22:15:20 +00:00
var value = getFromLocalStorage(lsKey);
2014-08-15 17:05:57 +00:00
2014-10-06 22:15:20 +00:00
if (value === null && isDefined(def)) {
2014-08-15 17:05:57 +00:00
value = def;
2014-10-06 22:15:20 +00:00
} else if (isObject(value) && isObject(def)) {
value = extend(def, value);
2014-08-15 17:05:57 +00:00
}
2014-10-13 22:36:11 +00:00
$parse(key).assign(scope, value);
2014-08-15 17:05:57 +00:00
2014-10-13 22:36:11 +00:00
return scope.$watch(key, function(newVal) {
2014-10-06 22:15:20 +00:00
addToLocalStorage(lsKey, newVal);
2014-10-13 22:36:11 +00:00
}, isObject(scope[key]));
2014-08-15 17:05:57 +00:00
};
2014-10-06 22:15:20 +00:00
// Return localStorageService.length
// ignore keys that not owned
var lengthOfLocalStorage = function() {
var count = 0;
var storage = $window[storageType];
for(var i = 0; i < storage.length; i++) {
if(storage.key(i).indexOf(prefix) === 0 ) {
count++;
}
}
return count;
};
2014-08-15 17:05:57 +00:00
return {
isSupported: browserSupportsLocalStorage,
getStorageType: getStorageType,
set: addToLocalStorage,
add: addToLocalStorage, //DEPRECATED
get: getFromLocalStorage,
keys: getKeysForLocalStorage,
remove: removeFromLocalStorage,
clearAll: clearAllFromLocalStorage,
bind: bindToScope,
deriveKey: deriveQualifiedKey,
2014-10-06 22:15:20 +00:00
length: lengthOfLocalStorage,
2014-08-15 17:05:57 +00:00
cookie: {
isSupported: browserSupportsCookies,
2014-08-15 17:05:57 +00:00
set: addToCookies,
add: addToCookies, //DEPRECATED
get: getFromCookies,
remove: removeFromCookies,
clearAll: clearAllFromCookies
}
};
}];
});
})( window, window.angular );