├── README.md
├── db
├── has.js
└── SQL.js
├── LocalDB.js
├── tests
├── runTests.html
├── LocalStorage.js
└── module.js
└── LocalStorage.js
/README.md:
--------------------------------------------------------------------------------
1 | Unfinished!
--------------------------------------------------------------------------------
/db/has.js:
--------------------------------------------------------------------------------
1 | define(["dojo/has"], function(has){
2 | has.add("indexed", !!window.IndexedDB);
3 | return has;
4 | });
--------------------------------------------------------------------------------
/LocalDB.js:
--------------------------------------------------------------------------------
1 | define(["./db/has!indexedb?./db/IndexedDB:sql?./db/SQL:./LocalStorage"], function(LocalDB){
2 | // module:
3 | // dojo/store/LocalDB
4 | // summary:
5 | // The module defines an object store based on local database access
6 | return LocalDB;
7 | });
8 |
--------------------------------------------------------------------------------
/tests/runTests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dojo CORE and BASE D.O.H. Unit Test Runner
5 |
6 |
7 | Redirecting to D.O.H runner.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/LocalStorage.js:
--------------------------------------------------------------------------------
1 | define([
2 | "doh/main",
3 | "../LocalStorage"
4 | ], function(doh, LocalStorage){
5 | var store = new LocalStorage({storeId: "test"});
6 | doh.register("localdb/tests/LocalStorage", {
7 | "io": {
8 | runTest: function(t){
9 | store.put({
10 | id: 1,
11 | name: "One",
12 | odd: true
13 | });
14 | doh.is(store.get(1).name, "One");
15 | doh.is(store.get(1).odd, true);
16 | doh.is(store.getIdentity(store.get(1)), 1);
17 | store.add({
18 | id: 2,
19 | name: "Two",
20 | odd: false
21 | });
22 | doh.is(store.get(2).name, "Two");
23 | doh.is(store.get(2).odd, false);
24 | doh.is(store.get(1).name, "One");
25 | var overwriteAllowed;
26 | try{
27 | store.put({
28 | id: 2,
29 | name: "Three",
30 | odd: false
31 | }, {overwrite: false});
32 | overwriteAllowed = true;
33 | }catch(e){
34 | }
35 | doh.f(overwriteAllowed);
36 | doh.is(store.get(2).name, "Two");
37 | doh.is(store.query().length, 2);
38 | var length = 0;
39 | store.query({odd:true}).forEach(function(object){
40 | doh.is(object.odd, true);
41 | length++;
42 | });
43 | doh.is(length, 1);
44 | store.remove(1);
45 | doh.is(store.get(1), undefined);
46 | store.remove(2);
47 | doh.is(store.get(2), undefined);
48 | doh.is(store.query().length, 0);
49 | store.query({odd:true}).forEach(function(object){
50 | doh.error("should be empty");
51 | });
52 | }
53 | }
54 | }, function(){}, function(){
55 | store.remove(1);
56 | store.remove(2);
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/tests/module.js:
--------------------------------------------------------------------------------
1 | define([
2 | "doh/main",
3 | "../LocalStorage",
4 | "../db/SQL"
5 | ], function(doh, LocalStorage, SQL){
6 | function testStore(StoreClass){
7 | var store = new StoreClass({storeId: "test"});
8 | doh.register("localdb/tests/LocalStorage",
9 | {
10 | "io": {
11 | runTest: function(t){
12 | store.put({
13 | id: 1,
14 | name: "One",
15 | odd: true
16 | });
17 | doh.is(store.get(1).name, "One");
18 | doh.is(store.get(1).odd, true);
19 | doh.is(store.getIdentity(store.get(1)), 1);
20 | store.add({
21 | id: 2,
22 | name: "Two",
23 | odd: false
24 | });
25 | doh.is(store.get(2).name, "Two");
26 | doh.is(store.get(2).odd, false);
27 | doh.is(store.get(1).name, "One");
28 | var overwriteAllowed;
29 | try{
30 | store.put({
31 | id: 2,
32 | name: "Three",
33 | odd: false
34 | }, {overwrite: false});
35 | overwriteAllowed = true;
36 | }catch(e){
37 | }
38 | doh.f(overwriteAllowed);
39 | doh.is(store.get(2).name, "Two");
40 | doh.is(store.query().length, 2);
41 | var length = 0;
42 | store.query({odd:true}).forEach(function(object){
43 | doh.is(object.odd, true);
44 | length++;
45 | });
46 | doh.is(length, 1);
47 | store.remove(1);
48 | doh.is(store.get(1), undefined);
49 | store.remove(2);
50 | doh.is(store.get(2), undefined);
51 | doh.is(store.query().length, 0);
52 | store.query({odd:true}).forEach(function(object){
53 | doh.error("should be empty");
54 | });
55 | }
56 | }
57 | }, function(){}, function(){
58 | store.remove(1);
59 | store.remove(2);
60 | });
61 | }
62 | testStore(SQL);
63 | testStore(LocalStorage);
64 | });
65 |
--------------------------------------------------------------------------------
/db/SQL.js:
--------------------------------------------------------------------------------
1 | define(["dojo/_base/declare"], function(declare) {
2 | // module:
3 | // dojo/store/LocalStorage
4 | // summary:
5 | // The module defines an object store based on local storage
6 |
7 |
8 | return declare([], {
9 | constructor: function(config){
10 | this.database = openDatabase(config.name || "db", true, true, true);// TODO: what are these arguments supposed to be?
11 | this.table = config.table;
12 | this.idColumn = config.idColumn || "id";
13 | this.indexPrefix = config.indexPrefix || "idx_";
14 | },
15 | idProperty: "id",
16 | selectColumns: ["*"],
17 | get: function(id){
18 | return when(this.executeSql("SELECT " + this.selectColumns.join(",") + " FROM " + this.table + " WHERE " + idColumn + "=?", [id]), function(result){
19 | return first(result.rows);
20 | });
21 | },
22 | getId: function(object){
23 | return object[idColumn];
24 | },
25 | "delete": function(id){
26 | return store.executeSql("DELETE FROM " + config.table + " WHERE " + idColumn + "=?", [id]); // Promise
27 | },
28 | identifyGeneratedKey: true,
29 | add: function(object, directives){
30 | var params = [], vals = [], cols = [];
31 | for(var i in object){
32 | if(object.hasOwnProperty(i)){
33 | cols.push(i);
34 | vals.push('?');
35 | params.push(object[i]);
36 | }
37 | }
38 | if(store.identifyGeneratedKey){
39 | params.idColumn = config.idColumn;
40 | }
41 | var sql = "INSERT INTO " + config.table + " (" + cols.join(',') + ") VALUES (" + vals.join(',') + ")";
42 | return when(store.executeSql(sql, params), function(results) {
43 | var id = results.insertId;
44 | object[idColumn] = id;
45 | return id;
46 | });
47 | },
48 | put: function(object, directives){
49 | directives = directives || {};
50 | var id = directives.id || object[this.idProperty];
51 | var overwrite = directives.overwrite;
52 | if(overwrite === undefined){
53 | overwrite = this.get(id);
54 | }
55 |
56 | if(!overwrite){
57 | store.add(object, directives);
58 | }
59 | var sql = "UPDATE " + config.table + " SET ";
60 | var first = true;
61 | var params = [];
62 | for(var i in object){
63 | if(object.hasOwnProperty(i)){
64 | if(first) first = false;
65 | else sql += ",";
66 | sql += i + "=?";
67 | params.push(object[i]);
68 | }
69 | }
70 | sql += " WHERE " + idColumn + "=?";
71 | params.push(object[idColumn]);
72 |
73 | return when(store.executeSql(sql, params), function(result){
74 | return id;
75 | });
76 | },
77 | query: function(query, options){
78 |
79 | },
80 | executeSql: function(sql, parameters){
81 | var deferred = defer();
82 | var result, error;
83 | database.executeSql(sql, parameters, function(value){
84 | deferred.resolve(result = value);
85 | }, function(e){
86 | deferred.reject(error = e);
87 | });
88 | // return synchronously if the data is already available.
89 | if(result){
90 | return result;
91 | }
92 | if(error){
93 | throw error;
94 | }
95 | return deferred.promise;
96 | }
97 |
98 | });
99 | });
100 |
--------------------------------------------------------------------------------
/LocalStorage.js:
--------------------------------------------------------------------------------
1 | define(["dojo/_base/declare", "dojo/store/Memory", "dojo/json"], function(declare, Memory, JSON) {
2 | // module:
3 | // dojo/store/LocalStorage
4 | // summary:
5 | // The module defines an object store based on local storage
6 |
7 |
8 | return declare([Memory], {
9 | // summary:
10 | // This is a local storage object store. It implements dojo.store.api.Store.
11 | // storeId: String
12 | // An identifier for the local store, allows you to have distinct local stores by setting unique ids on each
13 | storeId: "default-store",
14 | constructor: function(args){
15 | this.idPrefix = args.storeId + "-";
16 | },
17 | get: function(id){
18 | // summary:
19 | // Retrieves an object by its identity
20 | // id: Number
21 | // The identity to use to lookup the object
22 | // returns: Object
23 | // The object in the store that matches the given id.
24 | return JSON.parse(localStorage.getItem(this.idPrefix + id));
25 | },
26 | put: function(object, options){
27 | // summary:
28 | // Stores an object
29 | // object: Object
30 | // The object to store.
31 | // options: dojo.store.api.Store.PutDirectives??
32 | // Additional metadata for storing the data. Includes an "id"
33 | // property if a specific id is to be used.
34 | // returns: Number
35 | var data = this.data,
36 | index = this.index,
37 | options = options || {},
38 | idProperty = this.idProperty;
39 | var id = this.idPrefix + (object[idProperty] = (options && "id" in options) ? options.id : idProperty in object ? object[idProperty] : Math.random());
40 | if(typeof options.overwrite == "boolean"){
41 | if((localStorage.getItem(id) == null) == options.overwrite){
42 | throw new Error("Overwrite " + (options.overwrite ? "required" : "not allowed"));
43 | }
44 | }
45 | localStorage.setItem(id, JSON.stringify(object));
46 | return this.inherited(arguments);
47 | },
48 | remove: function(id){
49 | // summary:
50 | // Deletes an object by its identity
51 | // id: Number
52 | // The identity to use to delete the object
53 | // returns: Boolean
54 | // Returns true if an object was removed, falsy (undefined) if no object matched the id
55 | localStorage.removeItem(this.idPrefix + id);
56 | return this.inherited(arguments);
57 | },
58 | query: function(query, options){
59 | // summary:
60 | // Queries the store for objects.
61 | // query: Object
62 | // The query to use for retrieving objects from the store.
63 | // options: dojo.store.api.Store.QueryOptions?
64 | // The optional arguments to apply to the resultset.
65 | // returns: dojo.store.api.Store.QueryResults
66 | // The results of the query, extended with iterative methods.
67 | //
68 | // example:
69 | // Given the following store:
70 | //
71 | // | var store = new dojo.store.Memory({
72 | // | data: [
73 | // | {id: 1, name: "one", prime: false },
74 | // | {id: 2, name: "two", even: true, prime: true},
75 | // | {id: 3, name: "three", prime: true},
76 | // | {id: 4, name: "four", even: true, prime: false},
77 | // | {id: 5, name: "five", prime: true}
78 | // | ]
79 | // | });
80 | //
81 | // ...find all items where "prime" is true:
82 | //
83 | // | var results = store.query({ prime: true });
84 | //
85 | // ...or find all items where "even" is true:
86 | //
87 | // | var results = store.query({ even: true });
88 | if(!this._loaded){
89 | // load the data from local storage
90 | this._loaded = true;
91 | var index = this.index = {};
92 | var data = this.data = [];
93 | var idPrefix = this.idPrefix;
94 | var idPrefixLength = idPrefix.length;
95 | for(var i = 0, l = localStorage.length; i < l; i++){
96 | // iterate through each key
97 | var key = localStorage.key(i);
98 |
99 | if(key.slice(0, idPrefixLength) == idPrefix){
100 | var object = JSON.parse(localStorage.getItem(key));
101 | index[object[this.idProperty]] = data.push(object) - 1;
102 | }
103 | }
104 | }
105 | return this.inherited(arguments);
106 | }
107 | });
108 |
109 | });
110 |
--------------------------------------------------------------------------------