From 4dc2661ec8017c0add49f3b43dc7d6de1af216ec Mon Sep 17 00:00:00 2001 From: grevory Date: Wed, 31 Oct 2012 00:53:36 -0400 Subject: [PATCH] Cookie fallback support --- README.md | 2 +- demo-app.js | 1 + demo.html | 10 +++- localStorageModule.js | 131 +++++++++++++++++++++++++++++++++++------- 4 files changed, 121 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f0019a1..ef65ac0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ An Angular module that gives you access to the browsers local storage Remember to set your app name (settings.appPrefix) in the settings at the beginning of localStorageModule.js. To do: -- Set cookies as a failback for browsers that do not support local storage +- Add tests - Expand Readme Example use: diff --git a/demo-app.js b/demo-app.js index 9128eb2..46fc18f 100644 --- a/demo-app.js +++ b/demo-app.js @@ -6,4 +6,5 @@ var DemoCtrl = function($scope, localStorageService) { localStorageService.add('localStorageDemo',value); $scope.localStorageDemoValue = localStorageService.get('localStorageDemo'); }); + }; \ No newline at end of file diff --git a/demo.html b/demo.html index 639ede1..a7472f8 100644 --- a/demo.html +++ b/demo.html @@ -69,6 +69,8 @@ var YourCtrl = function($scope, localStorageService, ...) { localStorageService.add('localStorageKey','Add this!'); // Read that value back var value = localStorageService.get('localStorageKey'); + // You can also play with cookies the same way + localStorageService.cookie.add('localStorageKey','I am a cookie value now'); }

API Access

@@ -85,7 +87,7 @@ var YourCtrl = function($scope, localStorageService, ...) { isSupported - n/a + n/a Checks the browsers support for local storage Boolean for success @@ -113,6 +115,12 @@ var YourCtrl = function($scope, localStorageService, ...) { Warning Removes all local storage key-value pairs for this app. Boolean for success + + cookie + add | get | remove | clearAll + Each function within cookie uses the same arguments as the coresponding local storage functions + n/a + diff --git a/localStorageModule.js b/localStorageModule.js index a081259..8645618 100644 --- a/localStorageModule.js +++ b/localStorageModule.js @@ -1,19 +1,20 @@ -// Configure Angular Local Storage -var settings = { - - // You should set a prefix to avoid overwriting any local storage variables from the rest of your app - // prefix: 'youAppNameHere' - appPrefix: 'test' -}; - /* Start angularLocalStorage */ -var angularLocalStorage = angular.module('LocalStorageModule', []) +var angularLocalStorage = angular.module('LocalStorageModule', []); -// Set the prefix based on the settings object above -angularLocalStorage.constant('prefix', settings.appPrefix || ''); +// You should set a prefix to avoid overwriting any local storage variables from the rest of your app +// e.g. angularLocalStorage.constant('prefix', 'youAppName'); +angularLocalStorage.constant('prefix', 'ls'); +// 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 +angularLocalStorage.constant('cookie', { expiry:30, path: '/'}); -angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { +angularLocalStorage.service('localStorageService', [ + '$rootScope', + 'prefix', + 'cookie', + function($rootScope, prefix, cookie) { // If there is a prefix set in the config lets use that with an appended period for readability //var prefix = angularLocalStorage.constant; @@ -26,6 +27,7 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { try { return ('localStorage' in window && window['localStorage'] !== null); } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); return false; } }; @@ -37,7 +39,7 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { // If this browser does not support local storage use cookies if (!browserSupportsLocalStorage()) { - console.log('Cannot add to local storage. Get from cookies'); // todo + $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED'); return false; } @@ -47,7 +49,7 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { try { localStorage.setItem(prefix+key, value); } catch (e) { - console.error(e.Description); + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); return false; } return true; @@ -57,28 +59,27 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { // Example use: localStorageService.get('library'); // returns 'angular' var getFromLocalStorage = function (key) { if (!browserSupportsLocalStorage()) { - console.log('Cannot get from local storage. Use cookies'); // todo + $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED'); return false; } var item = localStorage.getItem(prefix+key); if (!item) return null; return item; - //or localStorage[key]; }; // Remove an item from local storage // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular' var removeFromLocalStorage = function (key) { if (!browserSupportsLocalStorage()) { - console.log('Cannot remove item from local storage. Remove from cookies'); // todo + $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED'); return false; } try { localStorage.removeItem(prefix+key); } catch (e) { - console.error(e.Description); + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); return false; } return true; @@ -90,7 +91,7 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { var clearAllFromLocalStorage = function () { if (!browserSupportsLocalStorage()) { - console.log('Cannot remove all items from local storage. Remove all app cookies'); // todo + $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED'); return false; } @@ -102,7 +103,7 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { try { removeFromLocalStorage(key.substr(prefixLength)); } catch (e) { - console.error(e.Description); + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); return false; } } @@ -110,12 +111,100 @@ angularLocalStorage.service('localStorageService', ['prefix', function(prefix) { return true; }; + // Checks the browser to see if cookies are supported + var browserSupportsCookies = function() { + try { + return navigator.cookieEnabled || + ("cookie" in document && (document.cookie.length > 0 || + (document.cookie = "test").indexOf.call(document.cookie, "test") > -1)); + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); + return false; + } + } + + // 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) { + + if (typeof value == "undefined") return false; + + if (!browserSupportsCookies()) { + $rootScope.$broadcast('LocalStorageModule.notification.error','COOKIES_NOT_SUPPORTED'); + return false; + } + + try { + var expiry = '', expiryDate = new Date(); + if (value === null) { + cookie.expiry = -1; + value = ''; + } + if (cookie.expiry !== 0) { + expiryDate.setTime(expiryDate.getTime() + (cookie.expiry*24*60*60*1000)); + expiry = "; expires="+expiryDate.toGMTString(); + } + document.cookie = prefix + key + "=" + encodeURIComponent(value) + expiry + "; path="+cookie.path; + } catch (e) { + $rootScope.$broadcast('LocalStorageModule.notification.error',e.Description); + 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()) { + $rootScope.$broadcast('LocalStorageModule.notification.error','COOKIES_NOT_SUPPORTED'); + return false; + } + + var cookies = 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(prefix+key+'=') == 0) { + return decodeURIComponent(thisCookie.substring(prefix.length+key.length+1,thisCookie.length)); + } + } + 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); + } + key = thisCookie.substring(prefixLength,thisCookie.indexOf('=')); + removeFromCookies(key); + } + } + + return { isSupported: browserSupportsLocalStorage, add: addToLocalStorage, get: getFromLocalStorage, remove: removeFromLocalStorage, - clearAll: clearAllFromLocalStorage + clearAll: clearAllFromLocalStorage, + cookie: { + add: addToCookies, + get: getFromCookies, + remove: removeFromCookies, + clearAll: clearAllFromCookies + } }; }]);