Skip to content

Commit

Permalink
# 0.1.0 (19 Mars 2014)
Browse files Browse the repository at this point in the history
* Added a changelog !
* Using localForage 0.1.1 with the new config options
* **Breaking change**: setPrefix has been removed, use the config function from now on
* Renamed all the functions to keep consistency with the localForage function names (set/get/remove/clearAll/getKeyAt/getLength/getDriver are renammed setItem/getItem/removeItem/clear/key/length/driver). The old function names are still available.
* Added a test to check for "InvalidStateError" due to private browsing in firefox and switching to localstorage when this is the case
* Fixed bug #4 [removeItem needs to use prefix](#4)
* Added missing package.json (for tests) and updated tests
  • Loading branch information
ocombe committed Mar 19, 2014
1 parent 146b675 commit 47457e8
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 74 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 0.1.0 (19 Mars 2014)
* Added a changelog !
* Using localForage 0.1.1 with the new config options
* **Breaking change**: setPrefix has been removed, use the config function from now on
* Renamed all the functions to keep consistency with the localForage function names (set/get/remove/clearAll/getKeyAt/getLength/getDriver are renammed setItem/getItem/removeItem/clear/key/length/driver). The old function names are still available.
* Added a test to check for "InvalidStateError" due to private browsing in firefox and switching to localstorage when this is the case
* Fixed bug #4 [removeItem needs to use prefix](https://github.com/ocombe/angular-localForage/issues/4)
* Added missing package.json (for tests) and updated tests
40 changes: 24 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ angular.module('yourModule', ['LocalForageModule']);
```js
angular.module('yourModule', ['LocalForageModule'])
.config(['$localForageProvider', function($localForageProvider){
$localForageProvider.setPrefix('newPrefix');
$localForageProvider.config({
driver : 'localStorageWrapper', // if you want to force a driver
name : 'myApp', // name of the database and prefix for your data
version : 1.0, // version of the database, you shouldn't have to use this
storeName : 'keyvaluepairs', // name of the table
description : 'some description'
});
}]);
```
- Use the ```$localForage``` service or the ```local-forage``` directive
Expand All @@ -37,7 +43,7 @@ angular.module('yourModule', ['LocalForageModule'])
.controller('yourCtrl', ['$scope', '$localForage', function($scope, $localForage) {
// Start fresh
$localForage.clearAll();
$localForage.set('myName','Olivier Combe').then(function() {
$localForage.setItem('myName','Olivier Combe').then(function() {
$localForage.get('myName').then(function(data) {
var myName = data;
});
Expand All @@ -55,21 +61,21 @@ angular.module('yourModule', ['LocalForageModule'])
## Functions :
- ```setDriver(driver)```: you can force the driver to use, check the [localForage documentation](https://github.com/mozilla/localForage#driver-selection-ie-forcing-localstorage) for more information

- ```getDriver()```: returns the current localForage driver (sync)
- ```driver()```: returns the current localForage driver (sync)

- ```set(key, value)```: stores data (async, promise)
- ```setItem(key, value)```: stores data (async, promise)

- ```get(key)```: retrieves stored data (async, promise)
- ```getItem(key)```: retrieves stored data (async, promise)

- ```remove(key)```: removes stored data (async, promise)
- ```removeItem(key)```: removes stored data (async, promise)

- ```clearAll()```: removed all stored data for your application based on the app prefix (lf by default) (async, promise)
- ```clear()```: removed all stored data for your application based on the app prefix (async, promise)

- ```getKeyAt(n)```: retrieves the key at n position in storage. Used internally for clearAll and getKeys functions. It doesn't take prefix into account (async, promise)
- ```key(n)```: retrieves the key at n position in storage. Used internally for clearAll and getKeys functions. It doesn't take prefix into account (async, promise)

- ```getKeys(driver)```: returns all the keys used for storage in your application based on the app prefix (lf by default) (async, promise)
- ```getKeys(driver)```: returns all the keys used for storage in your application. Be careful with it if you use localstorage because it will return all the keys (not just the ones with your prefix) (async, promise)

- ```getLength(driver)```: returns the number of items stored. Used internally for clearAll and getKeys functions. It doesn't take prefix into account (async, promise)
- ```length(driver)```: returns the number of items stored. Used internally for clearAll and getKeys functions. Be careful with it if you use localstorage because it will return all the keys (not just the ones with your prefix) (async, promise)

- ```bind($scope, key/params object)```: lets you directly bind a LocalForage value to a $scope variable
```js
Expand Down Expand Up @@ -106,7 +112,9 @@ You can configure the ```$localForageProvider``` to set your own prefix for stor
```js
angular.module('yourModule', ['LocalForageModule'])
.config(['$localForageProvider', function($localForageProvider){
$localForageProvider.setPrefix('newPrefix');
$localForageProvider.config({
name: 'yourprefix'
});
}]);
```

Expand All @@ -132,19 +140,19 @@ angular.module('yourModule', ['LocalForageModule'])
$localForageProvider.setDriver('localStorageWrapper');
}]);
```
## Unit tests

To retrieve all things needed, first run
## Unit tests
Download the required libs :

```
bower install
npm install
```

After, you just have to run :
Then start the tests with :

```
karma start
npm test
```

It will launch once Chrome and Firefox, edit karma.conf.js if you want to change something.
It will launch Chrome and Firefox, edit karma.conf.js if you want to change something.
137 changes: 92 additions & 45 deletions angular-localForage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@

(function(window, angular, undefined) {
'use strict';

var angularLocalForage = angular.module('LocalForageModule', ['ng']);
angularLocalForage.provider('$localForage', function() {
/**
* You should set a prefix to avoid overwriting any local storage variables from the rest of your app
* e.g. $localForageProvider.setPrefix('youAppName');
* With provider you can use config as this:
* myApp.config(function ($localForageProvider) {
* $localForageProvider.prefix = 'yourAppName';
* });
*/
this.prefix = 'lf'; // default prefix
window.localForageConfig = {
name: 'lf' // default prefix
};

// Send signals for each of the following actions ?
this.notify = {
Expand All @@ -25,7 +19,10 @@

// Setter for the prefix
this.setPrefix = function(prefix) {
this.prefix = prefix;
if(angular.isDefined(prefix) && prefix !== window.localForageConfig.name) {
window.localForageConfig.name = prefix;
localforage._initStorage(window.localForageConfig);
}
};

// Setter for the storage driver
Expand All @@ -36,7 +33,7 @@
this.setDriver = setDriver;

// Getter for the storage driver
var getDriver = function() {
var driver = function() {
return localforage.driver();
};

Expand All @@ -48,92 +45,133 @@
};
};

this.config = function(config) {
if(angular.isObject(config)) {
window.localForageConfig = config;
if(angular.isDefined(config.driver)) {
return setDriver(config.driver);
} else {
return localforage._initStorage(config);
}
}
}

this.$get = ['$rootScope', '$q', '$parse', function($rootScope, $q, $parse) {
var prefix = this.prefix;
var notify = this.notify;
var watchers = {};

// 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 prefix = function() {
return driver() === 'localStorageWrapper' ? 'lfp.' : '';
}

var onError = function(data, args, fct, deferred) {
if(data === 'InvalidStateError' && driver() === 'asyncStorage') {
setDriver('localStorageWrapper').then(function() {
fct(args).then(function(item) {
deferred.resolve(item);
}, function(data) {
deferred.reject(data);
});
}, function() {
deferred.reject(data);
});
} else {
deferred.reject(data);
}
}

// Directly adds a value to storage
var setItem = function(key, value) {
var deferred = $q.defer();
localforage.setItem(prefix + key, value).then(function() {
var deferred = $q.defer(),
args = arguments;
localforage.setItem(prefix() + key, value).then(function success() {
if(notify.setItem) {
$rootScope.$broadcast('LocalForageModule.setItem', {key: key, newvalue: value, driver: localforage.driver});
$rootScope.$broadcast('LocalForageModule.setItem', {key: key, newvalue: value, driver: localforage.driver()});
}
deferred.resolve();
}, function error(data) {
onError(data, args, setItem, deferred);
});

return deferred.promise;
};

// Directly get a value from storage
var getItem = function(key) {
var deferred = $q.defer();
localforage.getItem(prefix + key).then(function(item) {
var deferred = $q.defer(),
args = arguments;
localforage.getItem(prefix() + key).then(function success(item) {
deferred.resolve(item);
}, function error(data) {
onError(data, args, getItem, deferred);
});
return deferred.promise;
};

// Remove an item from storage
var removeItem = function(key) {
var promise = localforage.removeItem(key);
var promise = localforage.removeItem(prefix() + key);
if(notify.setItem) {
return promise.then(function(value) {
$rootScope.$broadcast('LocalForageModule.removeItem', {key: key, driver: localforage.driver});
$rootScope.$broadcast('LocalForageModule.removeItem', {key: key, driver: localforage.driver()});
});
} else {
return promise;
}
};

// Remove all data for this app from storage (we could use localforage.clear(); but we don't want to remove things without the prefix
var clearAll = function() {
var deferred = $q.defer();
var promises = [];
getKeys().then(function(keys) {
var clear = function() {
var deferred = $q.defer(),
args = arguments,
promises = [];
getKeys().then(function success(keys) {
angular.forEach(keys, function(key) {
promises.push(removeItem(key));
});

$q.all(promises).then(function() {
deferred.resolve();
});
}, function error(data) {
onError(data, args, clearAll, deferred);
});
return deferred.promise;
};
}

// Return the key for item at position n
var getKeyAt = function(n) {
var deferred = $q.defer(); // using $q to avoid using $apply
localforage.key(n).then(function(key) {
var key = function(n) {
var deferred = $q.defer(),
args = arguments;
localforage.key(n).then(function success(key) {
deferred.resolve(key);
}, function error(data) {
onError(data, args, key, deferred);
});
return deferred.promise;
};

var getLength = function() {
var deferred = $q.defer(); // using $q to avoid using $apply
localforage.length().then(function(length) {
var length = function() {
var deferred = $q.defer(),
args = arguments; // using $q to avoid using $apply
localforage.length().then(function success(length) {
deferred.resolve(length);
}, function error(data) {
onError(data, args, length, deferred);
});
return deferred.promise;
}

// Return the list of keys stored for this application
var getKeys = function() {
var deferred = $q.defer();
getLength().then(function(length) {
var deferred = $q.defer(),
args = arguments;
length().then(function success(length) {
var promises = [],
keys = [];
for(var i = 0; i < length; i++) {
promises.push(getKeyAt(i).then(function(key) {
if(key.indexOf(prefix) === 0) {
promises.push(key(i).then(function(key) {
if(key.indexOf(prefix()) === 0) {
keys.push(key);
}
}));
Expand All @@ -142,6 +180,8 @@
$q.all(promises).then(function() {
deferred.resolve(keys);
});
}, function error(data) {
onError(data, args, getKeys, deferred);
});
return deferred.promise;
}
Expand Down Expand Up @@ -216,14 +256,21 @@

return {
setDriver: setDriver,
getDriver: getDriver,
set: setItem,
get: getItem,
driver: driver,
getDriver: driver, // deprecated
setItem: setItem,
set: setItem, // deprecated
getItem: getItem,
get: getItem, // deprecated
remove: removeItem,
clearAll: clearAll,
getKeyAt: getKeyAt,
removeItem: removeItem, // deprecated
clear: clear,
clearAll: clear, // deprecated
key: key,
getKeyAt: key, // deprecated
getKeys: getKeys,
getLength: getLength,
length: length,
getLength: length, // deprecated
bind: bind,
unbind: unbind
};
Expand All @@ -243,4 +290,4 @@
}
}
}]);
})(window, window.angular);
})(window, window.angular);
2 changes: 1 addition & 1 deletion angular-localForage.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
{
"name": "angular-localForage",
"main": "angular-localForage.js",
"version": "0.0.3",
"version": "0.1.0",
"homepage": "https://github.com/ocombe/angular-localForage",
"authors": [
"Olivier Combe <[email protected]>"
],
"description": "Angular service & directive for https://github.com/mozilla/localForage (Offline storage, improved.)",
"keywords": [
"localstorage",
"local-storage",
"local-storage",,
"localForage",
"indexDB",
"webSQL",
"storage",
Expand All @@ -30,6 +31,6 @@
"angular-mocks": "~1.2.13"
},
"dependencies": {
"localforage": "*"
"localforage": "0.1.1"
}
}
Loading

0 comments on commit 47457e8

Please sign in to comment.