Comparing version 0.3.6 to 0.3.8
175
ngStorage.js
@@ -1,14 +0,19 @@ | ||
(function(angular, factory) { | ||
'use strict'; | ||
if (typeof define === 'function' && define.amd) { | ||
define('ngStorage', ['angular'], function(angular) { | ||
return factory(angular); | ||
}); | ||
} else { | ||
return factory(angular); | ||
} | ||
}(typeof angular === 'undefined' ? null : angular, function(angular) { | ||
(function (root, factory) { | ||
'use strict'; | ||
if (typeof define === 'function' && define.amd) { | ||
define(['angular'], factory); | ||
} else if (typeof exports === 'object') { | ||
module.exports = factory(require('angular')); | ||
} else { | ||
// Browser globals (root is window), we don't register it. | ||
factory(root.angular); | ||
} | ||
}(this , function (angular) { | ||
'use strict'; | ||
// RequireJS does not pass in Angular to us (will be undefined). | ||
// Fallback to window which should mostly be there. | ||
angular = (angular && angular.module ) ? angular : window.angular; | ||
/** | ||
@@ -19,3 +24,3 @@ * @ngdoc overview | ||
angular.module('ngStorage', []) | ||
return angular.module('ngStorage', []) | ||
@@ -29,3 +34,3 @@ /** | ||
.factory('$localStorage', _storageFactory('localStorage')) | ||
.provider('$localStorage', _storageProvider('localStorage')) | ||
@@ -39,17 +44,56 @@ /** | ||
.factory('$sessionStorage', _storageFactory('sessionStorage')); | ||
.provider('$sessionStorage', _storageProvider('sessionStorage')); | ||
function _storageFactory(storageType) { | ||
return [ | ||
'$rootScope', | ||
'$window', | ||
'$log', | ||
'$timeout', | ||
function _storageProvider(storageType) { | ||
return function () { | ||
var storageKeyPrefix = 'ngStorage-'; | ||
function( | ||
$rootScope, | ||
$window, | ||
$log, | ||
$timeout | ||
){ | ||
this.setKeyPrefix = function (prefix) { | ||
if (typeof prefix !== 'string') { | ||
throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setKeyPrefix() expects a String.'); | ||
} | ||
storageKeyPrefix = prefix; | ||
}; | ||
var serializer = angular.toJson; | ||
var deserializer = angular.fromJson; | ||
this.setSerializer = function (s) { | ||
if (typeof s !== 'function') { | ||
throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setSerializer expects a function.'); | ||
} | ||
serializer = s; | ||
}; | ||
this.setDeserializer = function (d) { | ||
if (typeof d !== 'function') { | ||
throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setDeserializer expects a function.'); | ||
} | ||
deserializer = d; | ||
}; | ||
// Note: This is not very elegant at all. | ||
this.get = function (key) { | ||
return deserializer(window[storageType].getItem(storageKeyPrefix + key)); | ||
}; | ||
// Note: This is not very elegant at all. | ||
this.set = function (key, value) { | ||
return window[storageType].setItem(key, serializer(value)); | ||
}; | ||
this.$get = [ | ||
'$rootScope', | ||
'$window', | ||
'$log', | ||
'$timeout', | ||
function( | ||
$rootScope, | ||
$window, | ||
$log, | ||
$timeout | ||
){ | ||
function isStorageSupported(storageType) { | ||
@@ -89,4 +133,8 @@ | ||
// The magic number 10 is used which only works for some keyPrefixes... | ||
// See https://github.com/gsklee/ngStorage/issues/137 | ||
var prefixLength = storageKeyPrefix.length; | ||
// #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app | ||
var webStorage = isStorageSupported(storageType) || ($log.warn('This browser does not support Web Storage!'), {setItem: function() {}, getItem: function() {}}), | ||
var webStorage = isStorageSupported(storageType) || ($log.warn('This browser does not support Web Storage!'), {setItem: angular.noop, getItem: angular.noop}), | ||
$storage = { | ||
@@ -98,2 +146,3 @@ $default: function(items) { | ||
$storage.$sync(); | ||
return $storage; | ||
@@ -103,7 +152,33 @@ }, | ||
for (var k in $storage) { | ||
'$' === k[0] || (delete $storage[k] && webStorage.removeItem('ngStorage-' + k)); | ||
'$' === k[0] || (delete $storage[k] && webStorage.removeItem(storageKeyPrefix + k)); | ||
} | ||
return $storage.$default(items); | ||
} | ||
}, | ||
$sync: function () { | ||
for (var i = 0, l = webStorage.length, k; i < l; i++) { | ||
// #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty) | ||
(k = webStorage.key(i)) && storageKeyPrefix === k.slice(0, prefixLength) && ($storage[k.slice(prefixLength)] = deserializer(webStorage.getItem(k))); | ||
} | ||
}, | ||
$apply: function() { | ||
var temp$storage; | ||
_debounce = null; | ||
if (!angular.equals($storage, _last$storage)) { | ||
temp$storage = angular.copy(_last$storage); | ||
angular.forEach($storage, function(v, k) { | ||
angular.isDefined(v) && '$' !== k[0] && webStorage.setItem(storageKeyPrefix + k, serializer(v)); | ||
delete temp$storage[k]; | ||
}); | ||
for (var k in temp$storage) { | ||
webStorage.removeItem(storageKeyPrefix + k); | ||
} | ||
_last$storage = angular.copy($storage); | ||
} | ||
}, | ||
}, | ||
@@ -113,43 +188,14 @@ _last$storage, | ||
try { | ||
webStorage = $window[storageType]; | ||
webStorage.length; | ||
} catch(e) { | ||
$log.warn('This browser does not support Web Storage!'); | ||
webStorage = {}; | ||
} | ||
$storage.$sync(); | ||
for (var i = 0, l = webStorage.length, k; i < l; i++) { | ||
// #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty) | ||
(k = webStorage.key(i)) && 'ngStorage-' === k.slice(0, 10) && ($storage[k.slice(10)] = angular.fromJson(webStorage.getItem(k))); | ||
} | ||
_last$storage = angular.copy($storage); | ||
$rootScope.$watch(function() { | ||
var temp$storage; | ||
_debounce || (_debounce = $timeout(function() { | ||
_debounce = null; | ||
if (!angular.equals($storage, _last$storage)) { | ||
temp$storage = angular.copy(_last$storage); | ||
angular.forEach($storage, function(v, k) { | ||
angular.isDefined(v) && '$' !== k[0] && webStorage.setItem('ngStorage-' + k, angular.toJson(v)); | ||
delete temp$storage[k]; | ||
}); | ||
for (var k in temp$storage) { | ||
webStorage.removeItem('ngStorage-' + k); | ||
} | ||
_last$storage = angular.copy($storage); | ||
} | ||
}, 100, false)); | ||
_debounce || (_debounce = $timeout($storage.$apply, 100, false)); | ||
}); | ||
// #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent` | ||
'localStorage' === storageType && $window.addEventListener && $window.addEventListener('storage', function(event) { | ||
if ('ngStorage-' === event.key.slice(0, 10)) { | ||
event.newValue ? $storage[event.key.slice(10)] = angular.fromJson(event.newValue) : delete $storage[event.key.slice(10)]; | ||
$window.addEventListener && $window.addEventListener('storage', function(event) { | ||
if (storageKeyPrefix === event.key.slice(0, prefixLength)) { | ||
event.newValue ? $storage[event.key.slice(prefixLength)] = deserializer(event.newValue) : delete $storage[event.key.slice(prefixLength)]; | ||
@@ -162,7 +208,12 @@ _last$storage = angular.copy($storage); | ||
$window.addEventListener && $window.addEventListener('beforeunload', function() { | ||
$storage.$sync(); | ||
}); | ||
return $storage; | ||
} | ||
]; | ||
}; | ||
} | ||
})); |
@@ -1,1 +0,1 @@ | ||
/*! ngstorage 0.3.6 | Copyright (c) 2015 Gias Kay Lee | MIT License */!function(a,b){"use strict";return"function"==typeof define&&define.amd?void define("ngStorage",["angular"],function(a){return b(a)}):b(a)}("undefined"==typeof angular?null:angular,function(a){"use strict";function b(b){return["$rootScope","$window","$log","$timeout",function(c,d,e,f){function g(a){var b;try{b=d[a]}catch(c){b=!1}if(b&&"localStorage"===a){var e="__"+Math.round(1e7*Math.random());try{localStorage.setItem(e,e),localStorage.removeItem(e)}catch(c){b=!1}}return b}var h,i,j=g(b)||(e.warn("This browser does not support Web Storage!"),{setItem:function(){},getItem:function(){}}),k={$default:function(b){for(var c in b)a.isDefined(k[c])||(k[c]=b[c]);return k},$reset:function(a){for(var b in k)"$"===b[0]||delete k[b]&&j.removeItem("ngStorage-"+b);return k.$default(a)}};try{j=d[b],j.length}catch(l){e.warn("This browser does not support Web Storage!"),j={}}for(var m,n=0,o=j.length;o>n;n++)(m=j.key(n))&&"ngStorage-"===m.slice(0,10)&&(k[m.slice(10)]=a.fromJson(j.getItem(m)));return h=a.copy(k),c.$watch(function(){var b;i||(i=f(function(){if(i=null,!a.equals(k,h)){b=a.copy(h),a.forEach(k,function(c,d){a.isDefined(c)&&"$"!==d[0]&&j.setItem("ngStorage-"+d,a.toJson(c)),delete b[d]});for(var c in b)j.removeItem("ngStorage-"+c);h=a.copy(k)}},100,!1))}),"localStorage"===b&&d.addEventListener&&d.addEventListener("storage",function(b){"ngStorage-"===b.key.slice(0,10)&&(b.newValue?k[b.key.slice(10)]=a.fromJson(b.newValue):delete k[b.key.slice(10)],h=a.copy(k),c.$apply())}),k}]}a.module("ngStorage",[]).factory("$localStorage",b("localStorage")).factory("$sessionStorage",b("sessionStorage"))}); | ||
/*! ngstorage 0.3.8 | Copyright (c) 2015 Gias Kay Lee | MIT License */!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):"object"==typeof exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){"use strict";function b(b){return function(){var c="ngStorage-";this.setKeyPrefix=function(a){if("string"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setKeyPrefix() expects a String.");c=a};var d=a.toJson,e=a.fromJson;this.setSerializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setSerializer expects a function.");d=a},this.setDeserializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+b+"Provider.setDeserializer expects a function.");e=a},this.get=function(a){return e(window[b].getItem(c+a))},this.set=function(a,c){return window[b].setItem(a,d(c))},this.$get=["$rootScope","$window","$log","$timeout",function(f,g,h,i){function j(a){var b;try{b=g[a]}catch(c){b=!1}if(b&&"localStorage"===a){var d="__"+Math.round(1e7*Math.random());try{localStorage.setItem(d,d),localStorage.removeItem(d)}catch(c){b=!1}}return b}var k,l,m=c.length,n=j(b)||(h.warn("This browser does not support Web Storage!"),{setItem:a.noop,getItem:a.noop}),o={$default:function(b){for(var c in b)a.isDefined(o[c])||(o[c]=b[c]);return o.$sync(),o},$reset:function(a){for(var b in o)"$"===b[0]||delete o[b]&&n.removeItem(c+b);return o.$default(a)},$sync:function(){for(var a,b=0,d=n.length;d>b;b++)(a=n.key(b))&&c===a.slice(0,m)&&(o[a.slice(m)]=e(n.getItem(a)))},$apply:function(){var b;if(l=null,!a.equals(o,k)){b=a.copy(k),a.forEach(o,function(e,f){a.isDefined(e)&&"$"!==f[0]&&n.setItem(c+f,d(e)),delete b[f]});for(var e in b)n.removeItem(c+e);k=a.copy(o)}}};return o.$sync(),k=a.copy(o),f.$watch(function(){l||(l=i(o.$apply,100,!1))}),g.addEventListener&&g.addEventListener("storage",function(b){c===b.key.slice(0,m)&&(b.newValue?o[b.key.slice(m)]=e(b.newValue):delete o[b.key.slice(m)],k=a.copy(o),f.$apply())}),g.addEventListener&&g.addEventListener("beforeunload",function(){o.$sync()}),o}]}}return a=a&&a.module?a:window.angular,a.module("ngStorage",[]).provider("$localStorage",b("localStorage")).provider("$sessionStorage",b("sessionStorage"))}); |
{ | ||
"name": "ngstorage", | ||
"version": "0.3.6", | ||
"version": "0.3.8", | ||
"author": "Gias Kay Lee", | ||
@@ -25,11 +25,11 @@ "licenses": [ | ||
"grunt-karma": "^0.x", | ||
"karma": "^0.12.31", | ||
"karma-chrome-launcher": "^0.1.4", | ||
"karma": "^0.13.2", | ||
"karma-chrome-launcher": "^0.2.0", | ||
"karma-firefox-launcher": "^0.1.3", | ||
"karma-mocha": "^0.1.0", | ||
"karma-phantomjs-launcher": "^0.1.4", | ||
"mocha": "^2.2.4" | ||
"karma-mocha": "^0.2.0", | ||
"karma-phantomjs-launcher": "^0.2.0", | ||
"mocha": "^2.2.4", | ||
"phantomjs": "^1.9.17" | ||
}, | ||
"dependencies": { | ||
} | ||
"dependencies": {} | ||
} |
ngStorage | ||
========= | ||
<!-- | ||
[![Build Status](https://travis-ci.org/gsklee/ngStorage.svg)](https://travis-ci.org/gsklee/ngStorage) | ||
--> | ||
[![Dependency Status](https://david-dm.org/gsklee/ngStorage.svg)](https://david-dm.org/gsklee/ngStorage) | ||
@@ -44,2 +41,3 @@ [![devDependency Status](https://david-dm.org/gsklee/ngStorage/dev-status.svg)](https://david-dm.org/gsklee/ngStorage#info=devDependencies) | ||
### cdnjs | ||
cdnjs now hosts ngStorage at <https://cdnjs.com/libraries/ngStorage> | ||
@@ -50,5 +48,15 @@ | ||
``` html | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.5/ngStorage.min.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.6/ngStorage.min.js"></script> | ||
``` | ||
### jsDelivr | ||
jsDelivr hosts ngStorage at <http://www.jsdelivr.com/#!ngstorage> | ||
To use is | ||
``` html | ||
<script src="https://cdn.jsdelivr.net/ngstorage/0.3.6/ngStorage.min.js"></script> | ||
``` | ||
Usage | ||
@@ -150,5 +158,60 @@ ===== | ||
### Usage from config phase | ||
To read and set values during the Angular config phase use the `.get/.set` | ||
functions provided by the provider. | ||
```javascript | ||
var app = angular.module('app', ['ngStorage']) | ||
.config(['$localStorageProvider', | ||
function ($localStorageProvider) { | ||
$localStorageProvider.get('MyKey'); | ||
$localStorageProvder.set('MyKey', { k: 'value' }); | ||
}]); | ||
``` | ||
### Prefix | ||
To change the prefix used by ngStorage use the provider function `setKeyPrefix` | ||
during the config phase. | ||
```javascript | ||
var app = angular.module('app', ['ngStorage']) | ||
.config(['$localStorageProvider', | ||
function ($localStorageProvider) { | ||
$localStorageProvider.setKeyPrefix('NewPrefix'); | ||
}]) | ||
``` | ||
### Minification | ||
Just run `$ npm install` to install dependencies. Then run `$ grunt` for minification. | ||
### Hints | ||
#### Watch the watch | ||
ngStorage internally uses an Angular watch to monitor changes to the `$storage`/`$localStorage` objects. That means that a digest cycle is required to persist your new values into the browser local storage. | ||
Normally this is not a problem, but, for example, if you launch a new window after saving a value... | ||
```javascript | ||
$scope.$storage.school = theSchool; | ||
$log.debug("launching " + url); | ||
var myWindow = $window.open("", "_self"); | ||
myWindow.document.write(response.data); | ||
``` | ||
the new values will not reliably be saved into the browser local storage. Allow a digest cycle to occur by using a zero-value `$timeout` as: | ||
```javascript | ||
$scope.$storage.school = theSchool; | ||
$log.debug("launching and saving the new value" + url); | ||
$timeout(function(){ | ||
var myWindow = $window.open("", "_self"); | ||
myWindow.document.write(response.data); | ||
}); | ||
``` | ||
And your new values will be persisted correctly. | ||
Todos | ||
@@ -155,0 +218,0 @@ ===== |
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
20748
169
223
12
3