From 9aed91157dad457b0d548ad6701d4e10836e60da Mon Sep 17 00:00:00 2001 From: David Martin Date: Thu, 6 Nov 2014 15:50:26 +0000 Subject: [PATCH 1/2] Listen for change event for bound values When you call localStorageService.bind, an event listener is now registered that is fired when the value of the local storage key changes, which updates the value and calls scope.$apply(). --- dist/angular-local-storage.js | 19 ++++++++++++++--- dist/angular-local-storage.min.js | 4 ++-- src/angular-local-storage.js | 17 ++++++++++++++-- test/spec/localStorageSpec.js | 34 +++++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/dist/angular-local-storage.js b/dist/angular-local-storage.js index 15b40b0..831de17 100644 --- a/dist/angular-local-storage.js +++ b/dist/angular-local-storage.js @@ -1,6 +1,6 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.5 - 2014-11-04 + * @version v0.1.5 - 2014-11-06 * @link https://github.com/grevory/angular-local-storage * @author grevory * @license MIT License, http://www.opensource.org/licenses/MIT @@ -181,7 +181,6 @@ angularLocalStorage.provider('localStorageService', function() { // Directly get a value from local storage // Example use: localStorageService.get('library'); // returns 'angular' var getFromLocalStorage = function (key) { - if (!browserSupportsLocalStorage || self.storageType === 'cookie') { if (!browserSupportsLocalStorage) { $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED'); @@ -411,9 +410,23 @@ angularLocalStorage.provider('localStorageService', function() { $parse(key).assign(scope, value); - return scope.$watch(key, function(newVal) { + var onKeyUpdated = function (event) { + if (event.key == deriveQualifiedKey(key)) { + scope[key] = getFromLocalStorage(key); + scope.$apply(); + } + }; + + $window.addEventListener("storage", onKeyUpdated, false); + + var unregisterWatch = scope.$watch(key, function (newVal) { addToLocalStorage(lsKey, newVal); }, isObject(scope[key])); + + return function () { + unregisterWatch(); + $window.removeEventListener("storage", onKeyUpdated); + }; }; // Return localStorageService.length diff --git a/dist/angular-local-storage.min.js b/dist/angular-local-storage.min.js index 7e00974..f4f0855 100644 --- a/dist/angular-local-storage.min.js +++ b/dist/angular-local-storage.min.js @@ -1,7 +1,7 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.5 - 2014-11-04 + * @version v0.1.5 - 2014-11-06 * @link https://github.com/grevory/angular-local-storage * @author grevory * @license MIT License, http://www.opensource.org/licenses/MIT - */!function(a,b){"use strict";function c(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))}var d=b.isDefined,e=b.isUndefined,f=b.isNumber,g=b.isObject,h=b.isArray,i=b.extend,j=b.toJson,k=b.fromJson,l=b.module("LocalStorageModule",[]);l.provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/"},this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(a){return this.prefix=a,this},this.setStorageType=function(a){return this.storageType=a,this},this.setStorageCookie=function(a,b){return this.cookie={expiry:a,path:b},this},this.setStorageCookieDomain=function(a){return this.cookie.domain=a,this},this.setNotify=function(a,b){return this.notify={setItem:a,removeItem:b},this},this.$get=["$rootScope","$window","$document","$parse",function(a,b,l,m){var n,o=this,p=o.prefix,q=o.cookie,r=o.notify,s=o.storageType;l?l[0]&&(l=l[0]):l=document,"."!==p.substr(-1)&&(p=p?p+".":"");var t=function(a){return p+a},u=function(){try{var c=s in b&&null!==b[s],d=t("__"+Math.round(1e7*Math.random()));return c&&(n=b[s],n.setItem(d,""),n.removeItem(d)),c}catch(e){return s="cookie",a.$broadcast("LocalStorageModule.notification.error",e.message),!1}}(),v=function(b,c){if(e(c)?c=null:(g(c)||h(c)||f(+c||c))&&(c=j(c)),!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:"cookie"}),B(b,c);try{(g(c)||h(c))&&(c=j(c)),n&&n.setItem(t(b),c),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:o.storageType})}catch(d){return a.$broadcast("LocalStorageModule.notification.error",d.message),B(b,c)}return!0},w=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),C(b);var d=n?n.getItem(t(b)):null;return d&&"null"!==d?"{"===d.charAt(0)||"["===d.charAt(0)||c(d)?k(d):d:null},x=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:"cookie"}),D(b);try{n.removeItem(t(b)),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:o.storageType})}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),D(b)}return!0},y=function(){if(!u)return a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),!1;var b=p.length,c=[];for(var d in n)if(d.substr(0,b)===p)try{c.push(d.substr(b))}catch(e){return a.$broadcast("LocalStorageModule.notification.error",e.Description),[]}return c},z=function(b){b=b||"";var c=p.slice(0,-1),d=new RegExp(c+"."+b);if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),E();var e=p.length;for(var f in n)if(d.test(f))try{x(f.substr(e))}catch(g){return a.$broadcast("LocalStorageModule.notification.error",g.message),E()}return!0},A=function(){try{return b.navigator.cookieEnabled||"cookie"in l&&(l.cookie.length>0||(l.cookie="test").indexOf.call(l.cookie,"test")>-1)}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),!1}}(),B=function(b,c){if(e(c))return!1;if((h(c)||g(c))&&(c=j(c)),!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",f=new Date,i="";if(null===c?(f.setTime(f.getTime()+-864e5),d="; expires="+f.toGMTString(),c=""):0!==q.expiry&&(f.setTime(f.getTime()+24*q.expiry*60*60*1e3),d="; expires="+f.toGMTString()),b){var k="; path="+q.path;q.domain&&(i="; domain="+q.domain),l.cookie=t(b)+"="+encodeURIComponent(c)+d+k+i}}catch(m){return a.$broadcast("LocalStorageModule.notification.error",m.message),!1}return!0},C=function(b){if(!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=l.cookie&&l.cookie.split(";")||[],d=0;d0||(l.cookie="test").indexOf.call(l.cookie,"test")>-1)}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),!1}}(),B=function(b,c){if(e(c))return!1;if((h(c)||g(c))&&(c=j(c)),!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",f=new Date,i="";if(null===c?(f.setTime(f.getTime()+-864e5),d="; expires="+f.toGMTString(),c=""):0!==q.expiry&&(f.setTime(f.getTime()+24*q.expiry*60*60*1e3),d="; expires="+f.toGMTString()),b){var k="; path="+q.path;q.domain&&(i="; domain="+q.domain),l.cookie=t(b)+"="+encodeURIComponent(c)+d+k+i}}catch(m){return a.$broadcast("LocalStorageModule.notification.error",m.message),!1}return!0},C=function(b){if(!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=l.cookie&&l.cookie.split(";")||[],d=0;d Date: Thu, 27 Nov 2014 12:54:18 +0000 Subject: [PATCH 2/2] updated to binding When local storage for a bound object is updated, it now extends the current object as opposed to overwriting it (this is to preserve unserializable properties, e.g. functions) --- dist/angular-local-storage.js | 13 ++++++++----- dist/angular-local-storage.min.js | 4 ++-- src/angular-local-storage.js | 11 +++++++---- test/spec/localStorageSpec.js | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/dist/angular-local-storage.js b/dist/angular-local-storage.js index 831de17..c0f7518 100644 --- a/dist/angular-local-storage.js +++ b/dist/angular-local-storage.js @@ -1,6 +1,6 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.5 - 2014-11-06 + * @version v0.1.5 - 2014-11-27 * @link https://github.com/grevory/angular-local-storage * @author grevory * @license MIT License, http://www.opensource.org/licenses/MIT @@ -407,22 +407,25 @@ angularLocalStorage.provider('localStorageService', function() { } else if (isObject(value) && isObject(def)) { value = extend(def, value); } - $parse(key).assign(scope, value); var onKeyUpdated = function (event) { if (event.key == deriveQualifiedKey(key)) { - scope[key] = getFromLocalStorage(key); + var updated = getFromLocalStorage(key); + if(scope[key] && typeof scope[key] === "object"){ + angular.extend(scope[key], updated); + } + else { + scope[key] = updated; + } scope.$apply(); } }; - $window.addEventListener("storage", onKeyUpdated, false); var unregisterWatch = scope.$watch(key, function (newVal) { addToLocalStorage(lsKey, newVal); }, isObject(scope[key])); - return function () { unregisterWatch(); $window.removeEventListener("storage", onKeyUpdated); diff --git a/dist/angular-local-storage.min.js b/dist/angular-local-storage.min.js index f4f0855..88e51c7 100644 --- a/dist/angular-local-storage.min.js +++ b/dist/angular-local-storage.min.js @@ -1,7 +1,7 @@ /** * An Angular module that gives you access to the browsers local storage - * @version v0.1.5 - 2014-11-06 + * @version v0.1.5 - 2014-11-27 * @link https://github.com/grevory/angular-local-storage * @author grevory * @license MIT License, http://www.opensource.org/licenses/MIT - */!function(a,b){"use strict";function c(a){return/^-?\d+\.?\d*$/.test(a.replace(/["']/g,""))}var d=b.isDefined,e=b.isUndefined,f=b.isNumber,g=b.isObject,h=b.isArray,i=b.extend,j=b.toJson,k=b.fromJson,l=b.module("LocalStorageModule",[]);l.provider("localStorageService",function(){this.prefix="ls",this.storageType="localStorage",this.cookie={expiry:30,path:"/"},this.notify={setItem:!0,removeItem:!1},this.setPrefix=function(a){return this.prefix=a,this},this.setStorageType=function(a){return this.storageType=a,this},this.setStorageCookie=function(a,b){return this.cookie={expiry:a,path:b},this},this.setStorageCookieDomain=function(a){return this.cookie.domain=a,this},this.setNotify=function(a,b){return this.notify={setItem:a,removeItem:b},this},this.$get=["$rootScope","$window","$document","$parse",function(a,b,l,m){var n,o=this,p=o.prefix,q=o.cookie,r=o.notify,s=o.storageType;l?l[0]&&(l=l[0]):l=document,"."!==p.substr(-1)&&(p=p?p+".":"");var t=function(a){return p+a},u=function(){try{var c=s in b&&null!==b[s],d=t("__"+Math.round(1e7*Math.random()));return c&&(n=b[s],n.setItem(d,""),n.removeItem(d)),c}catch(e){return s="cookie",a.$broadcast("LocalStorageModule.notification.error",e.message),!1}}(),v=function(b,c){if(e(c)?c=null:(g(c)||h(c)||f(+c||c))&&(c=j(c)),!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:"cookie"}),B(b,c);try{(g(c)||h(c))&&(c=j(c)),n&&n.setItem(t(b),c),r.setItem&&a.$broadcast("LocalStorageModule.notification.setitem",{key:b,newvalue:c,storageType:o.storageType})}catch(d){return a.$broadcast("LocalStorageModule.notification.error",d.message),B(b,c)}return!0},w=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),C(b);var d=n?n.getItem(t(b)):null;return d&&"null"!==d?"{"===d.charAt(0)||"["===d.charAt(0)||c(d)?k(d):d:null},x=function(b){if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:"cookie"}),D(b);try{n.removeItem(t(b)),r.removeItem&&a.$broadcast("LocalStorageModule.notification.removeitem",{key:b,storageType:o.storageType})}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),D(b)}return!0},y=function(){if(!u)return a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),!1;var b=p.length,c=[];for(var d in n)if(d.substr(0,b)===p)try{c.push(d.substr(b))}catch(e){return a.$broadcast("LocalStorageModule.notification.error",e.Description),[]}return c},z=function(b){b=b||"";var c=p.slice(0,-1),d=new RegExp(c+"."+b);if(!u||"cookie"===o.storageType)return u||a.$broadcast("LocalStorageModule.notification.warning","LOCAL_STORAGE_NOT_SUPPORTED"),E();var e=p.length;for(var f in n)if(d.test(f))try{x(f.substr(e))}catch(g){return a.$broadcast("LocalStorageModule.notification.error",g.message),E()}return!0},A=function(){try{return b.navigator.cookieEnabled||"cookie"in l&&(l.cookie.length>0||(l.cookie="test").indexOf.call(l.cookie,"test")>-1)}catch(c){return a.$broadcast("LocalStorageModule.notification.error",c.message),!1}}(),B=function(b,c){if(e(c))return!1;if((h(c)||g(c))&&(c=j(c)),!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",f=new Date,i="";if(null===c?(f.setTime(f.getTime()+-864e5),d="; expires="+f.toGMTString(),c=""):0!==q.expiry&&(f.setTime(f.getTime()+24*q.expiry*60*60*1e3),d="; expires="+f.toGMTString()),b){var k="; path="+q.path;q.domain&&(i="; domain="+q.domain),l.cookie=t(b)+"="+encodeURIComponent(c)+d+k+i}}catch(m){return a.$broadcast("LocalStorageModule.notification.error",m.message),!1}return!0},C=function(b){if(!A)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=l.cookie&&l.cookie.split(";")||[],d=0;d0||(m.cookie="test").indexOf.call(m.cookie,"test")>-1)}catch(b){return a.$broadcast("LocalStorageModule.notification.error",b.message),!1}}(),C=function(b,c){if(e(c))return!1;if((h(c)||g(c))&&(c=j(c)),!B)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;try{var d="",f=new Date,i="";if(null===c?(f.setTime(f.getTime()+-864e5),d="; expires="+f.toGMTString(),c=""):0!==r.expiry&&(f.setTime(f.getTime()+24*r.expiry*60*60*1e3),d="; expires="+f.toGMTString()),b){var k="; path="+r.path;r.domain&&(i="; domain="+r.domain),m.cookie=u(b)+"="+encodeURIComponent(c)+d+k+i}}catch(l){return a.$broadcast("LocalStorageModule.notification.error",l.message),!1}return!0},D=function(b){if(!B)return a.$broadcast("LocalStorageModule.notification.error","COOKIES_NOT_SUPPORTED"),!1;for(var c=m.cookie&&m.cookie.split(";")||[],d=0;d