├── README.md
├── bower.json
└── src
└── indexeddb.js
/README.md:
--------------------------------------------------------------------------------
1 | angular-indexedDB
2 | =================
3 |
4 | An angularjs serviceprovider to utilize indexedDB with angular
5 |
6 | ####Important: This repository isn't maintained by me anymore. Look [over here](https://github.com/bramski/angular-indexedDB) for current versions, as [Bram Whillock](https://github.com/bramski) took over as main contributor.
7 |
8 | ## Installation
9 |
10 | For installation the use of Bower is recommended.
11 |
12 | ### Bower
13 | Call the following command on your command line:
14 |
15 | ```sh
16 | bower install --save angularjs-indexedDB
17 | ```
18 |
19 | And add the following line to your html file, for example `index.html`:
20 |
21 | ```html
22 |
23 | ```
24 |
25 |
26 | ### Manual
27 |
28 | - Download file.
29 | - Add the following line to your html file:
30 |
31 | ```html
32 |
33 | ```
34 |
35 | ## Usage
36 |
37 | Normally, and as a recommendation, you have only one indexedDB per app.
38 | Thus in your `app.js` where you define your module, you do:
39 |
40 | ```javascript
41 | angular.module('myModuleName', ['xc.indexedDB'])
42 | .config(function ($indexedDBProvider) {
43 | $indexedDBProvider
44 | .connection('myIndexedDB')
45 | .upgradeDatabase(myVersion, function(event, db, tx){
46 | var objStore = db.createObjectStore('people', {keyPath: 'ssn'});
47 | objStore.createIndex('name_idx', 'name', {unique: false});
48 | objStore.createIndex('age_idx', 'age', {unique: false});
49 | });
50 | });
51 | ```
52 | The connection method takes the databasename as parameter,
53 | the upgradeCallback has 3 parameters:
54 | function callback(event, database, transaction). For upgrading your db structure, see
55 | https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB.
56 |
57 | You can also define your own error handlers, overwriting the default ones, which log to console.
58 |
59 |
60 | Inside your controller you use `$indexedDB` like this:
61 |
62 | ```javascript
63 | angular.module('myModuleName')
64 | .controller('myControllerName', function($scope, $indexedDB) {
65 |
66 | $scope.objects = [];
67 |
68 | var OBJECT_STORE_NAME = 'people';
69 |
70 | /**
71 | * @type {ObjectStore}
72 | */
73 | var myObjectStore = $indexedDB.objectStore(OBJECT_STORE_NAME);
74 |
75 | myObjectStore.insert({"ssn": "444-444-222-111","name": "John Doe", "age": 57}).then(function(e){...});
76 |
77 | myObjectStore.getAll().then(function(results) {
78 | // Update scope
79 | $scope.objects = results;
80 | });
81 |
82 | /**
83 | * execute a query:
84 | * presuming we've an index on 'age' field called 'age_idx'
85 | * find all persons older than 40 years
86 | */
87 |
88 | var myQuery = $indexedDB.queryBuilder().$index('age_idx').$gt(40).$asc.compile();
89 | myObjectStore.each(myQuery).then(function(cursor){
90 | cursor.key;
91 | cursor.value;
92 | ...
93 | });
94 | });
95 | ```
96 |
97 | QueryBuilder aka IDBKeyRange maybe needs some revision.
98 | This is all the info you get for now, for more read the code, it's ndoc-annotated!
99 |
100 | Important note: this software is in alpha state and therefore it's used at your own risk,
101 | don't make me liable for any damages or loss of data!
102 |
103 | Status Update: I'm sorry to say that I've abandoned angularJS for now and therefore have no plans for features or updates. This may change in the future. Apart from that I will apply updates submitted as pull requests when I find the time and see use.
104 |
105 | Anyone willing to join as active developer is welcome to drop me a note and help keep this project alive.
106 |
107 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-indexedDB",
3 | "version": "0.0.0",
4 | "homepage": "https://github.com/bramski/angular-indexedDB",
5 | "authors": [
6 | "webcss "
7 | ],
8 | "description": "An angularjs serviceprovider to utilize indexedDB with angular",
9 | "main": "src/indexeddb.js",
10 | "keywords": [
11 | "angularjs",
12 | "indexeddb",
13 | "angular"
14 | ],
15 | "license": "MIT"
16 | }
17 |
--------------------------------------------------------------------------------
/src/indexeddb.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license $indexedDBProvider
3 | * (c) 2013 Clemens Capitain (webcss)
4 | * License: MIT
5 | */
6 |
7 | 'use strict';
8 |
9 | angular.module('xc.indexedDB', []).provider('$indexedDB', function() {
10 | var module = this,
11 | /** IDBTransaction mode constants */
12 | READONLY = "readonly",
13 | READWRITE = "readwrite",
14 | VERSIONCHANGE = "versionchange",
15 | /** IDBCursor direction and skip behaviour constants */
16 | NEXT = "next",
17 | NEXTUNIQUE = "nextunique",
18 | PREV = "prev",
19 | PREVUNIQUE = "prevunique";
20 |
21 | /** predefined variables */
22 | module.dbName = '';
23 | module.dbVersion = 1;
24 | module.db = null;
25 | module.dbPromise = null;
26 | module.debugMode = false;
27 |
28 | /** predefined callback functions, can be customized in angular.config */
29 | module.onTransactionComplete = function(e) {
30 | if(module.debugMode) console.log('Transaction completed.');
31 | };
32 | module.onTransactionAbort = function(e) {
33 | if(module.debugMode) console.log('Transaction aborted: '+ (e.target.webkitErrorMessage || e.target.error.message || e.target.errorCode));
34 | };
35 | module.onTransactionError = function(e) {
36 | if(module.debugMode) console.log('Transaction failed: ' + e.target.errorCode);
37 | };
38 | module.onDatabaseError = function(e) {
39 | if(module.debugMode) alert("Database error: " + (e.target.webkitErrorMessage || e.target.errorCode));
40 | };
41 | module.onDatabaseBlocked = function(e) {
42 | // If some other tab is loaded with the database, then it needs to be closed
43 | // before we can proceed.
44 | if(module.debugMode) alert("Database is blocked. Try close other tabs with this page open and reload this page!");
45 | };
46 |
47 | /**
48 | * @ngdoc function
49 | * @name $indexedDBProvider.connection
50 | * @function
51 | *
52 | * @description
53 | * sets the name of the database to use
54 | *
55 | * @param {string} databaseName database name.
56 | * @returns {object} this
57 | */
58 | module.connection = function(databaseName) {
59 | module.dbName = databaseName;
60 | return this;
61 | };
62 |
63 | /**
64 | * @ngdoc function
65 | * @name $indexedDBProvider.upgradeDatabase
66 | * @function
67 | *
68 | * @description provides version number and steps to upgrade the database wrapped in a
69 | * callback function
70 | *
71 | * @param {number} newVersion new version number for the database.
72 | * @param {function} callback the callback which proceeds the upgrade
73 | * @returns {object} this
74 | */
75 | module.upgradeDatabase = function(newVersion, callback) {
76 | module.dbVersion = newVersion;
77 | module.upgradeCallback = callback;
78 | return this;
79 | };
80 |
81 | module.$get = ['$q', '$rootScope', '$window', function($q, $rootScope, $window) {
82 |
83 | if(!('indexedDB' in $window)) {
84 | $window.indexedDB = $window.mozIndexedDB || $window.webkitIndexedDB || $window.msIndexedDB;
85 | }
86 |
87 | var IDBKeyRange = $window.IDBKeyRange || $window.mozIDBKeyRange || $window.webkitIDBKeyRange || $window.msIDBKeyRange;
88 |
89 | /**
90 | * @ngdoc object
91 | * @name defaultQueryOptions
92 | * @function
93 | *
94 | * @description optionally specify for cursor requests:
95 | * - which index to use
96 | * - a keyRange to apply
97 | * - the direction of traversal (bottom to top/top to bottom)
98 | */
99 | var defaultQueryOptions = {
100 | useIndex: undefined,
101 | keyRange: null,
102 | direction: NEXT
103 | };
104 | /**
105 | * @ngdoc object
106 | * @name dbPromise
107 | * @function
108 | *
109 | * @description open the database specified in $indexedDBProvider.connection and
110 | * $indexdDBProvider.upgradeDatabase and returns a promise for this connection
111 | * @params
112 | * @returns {object} promise $q.promise to fullfill connection
113 | */
114 | var dbPromise = function() {
115 | var dbReq, deferred;
116 |
117 | if (!module.dbPromise) {
118 | deferred = $q.defer();
119 | module.dbPromise = deferred.promise;
120 |
121 | dbReq = $window.indexedDB.open(module.dbName, module.dbVersion || 1);
122 | dbReq.onsuccess = function(e) {
123 | module.db = dbReq.result;
124 | $rootScope.$apply(function(){
125 | deferred.resolve(module.db);
126 | });
127 | };
128 | dbReq.onblocked = module.onDatabaseBlocked;
129 | dbReq.onerror = module.onDatabaseError;
130 | dbReq.onupgradeneeded = function(e) {
131 | var db = e.target.result, tx = e.target.transaction;
132 | if(module.debugMode) console.log('upgrading database "' + db.name + '" from version ' + e.oldVersion+
133 | ' to version ' + e.newVersion + '...');
134 | module.upgradeCallback && module.upgradeCallback(e, db, tx);
135 | };
136 | }
137 |
138 | return module.dbPromise;
139 | };
140 | /**
141 | * @ngdoc object
142 | * @name ObjectStore
143 | * @function
144 | *
145 | * @description wrapper for IDBObjectStore
146 | *
147 | * @params {string} storeName name of the objectstore
148 | */
149 | var ObjectStore = function(storeName) {
150 | this.storeName = storeName;
151 | this.transaction = undefined;
152 | };
153 | ObjectStore.prototype = {
154 | /**
155 | * @ngdoc method
156 | * @name ObjectStore.internalObjectStore
157 | * @function
158 | *
159 | * @description used internally to retrieve an objectstore
160 | * with the correct transaction mode
161 | *
162 | * @params {string} storeName name of the objectstore
163 | * @params {string} mode transaction mode to use for operation
164 | * @returns {object} IDBObjectStore the objectstore in question
165 | */
166 | internalObjectStore: function(storeName, mode) {
167 | var me = this;
168 | return dbPromise().then(function(db){
169 | me.transaction = db.transaction([storeName], mode || READONLY);
170 | me.transaction.oncomplete = module.onTransactionComplete;
171 | me.transaction.onabort = module.onTransactionAbort;
172 | me.onerror = module.onTransactionError;
173 |
174 | return me.transaction.objectStore(storeName);
175 | });
176 | },
177 | /**
178 | * @ngdoc method
179 | * @name ObjectStore.abort
180 | * @function
181 | *
182 | * @description abort the current transaction
183 | */
184 | "abort": function() {
185 | if (this.transaction) {
186 | this.transaction.abort();
187 | }
188 | },
189 | /**
190 | * @ngdoc method
191 | * @name ObjectStore.insert
192 | * @function
193 | *
194 | * @description wrapper for IDBObjectStore.add.
195 | * input data can be a single object or an array of objects for
196 | * bulk insertions within a single transaction
197 | *
198 | * @params {object or array} data the data to insert
199 | * @returns {object} $q.promise a promise on successfull execution
200 | */
201 | "insert": function(data){
202 | var d = $q.defer();
203 | return this.internalObjectStore(this.storeName, READWRITE).then(function(store){
204 | var req;
205 | if (angular.isArray(data)) {
206 | data.forEach(function(item, i){
207 | req = store.add(item);
208 | req.onnotify = function(e) {
209 | $rootScope.$apply(function(){
210 | d.notify(e.target.result);
211 | });
212 | }
213 | req.onerror = function(e) {
214 | $rootScope.$apply(function(){
215 | d.reject(e.target.result);
216 | });
217 | };
218 | req.onsuccess = function(e) {
219 | if(i == data.length - 1) {
220 | $rootScope.$apply(function(){
221 | d.resolve(e.target.result);
222 | });
223 | }
224 | };
225 | });
226 | } else {
227 | req = store.add(data);
228 | req.onsuccess = req.onerror = function(e) {
229 | $rootScope.$apply(function(){
230 | d.resolve(e.target.result);
231 | });
232 | };
233 | }
234 | return d.promise;
235 | });
236 | },
237 | /**
238 | * @ngdoc method
239 | * @name ObjectStore.upsert
240 | * @function
241 | *
242 | * @description wrapper for IDBObjectStore.put.
243 | * modifies existing values or inserts as new value if nonexistant
244 | * input data can be a single object or an array of objects for
245 | * bulk updates/insertions within a single transaction
246 | *
247 | * @params {object or array} data the data to upsert
248 | * @returns {object} $q.promise a promise on successfull execution
249 | */
250 | "upsert": function(data){
251 | var d = $q.defer();
252 | return this.internalObjectStore(this.storeName, READWRITE).then(function(store){
253 | var req;
254 | if (angular.isArray(data)) {
255 | data.forEach(function(item, i){
256 | req = store.put(item);
257 | req.onnotify = function(e) {
258 | $rootScope.$apply(function(){
259 | d.notify(e.target.result);
260 | });
261 | }
262 | req.onerror = function(e) {
263 | $rootScope.$apply(function(){
264 | d.reject(e.target.result);
265 | });
266 | };
267 | req.onsuccess = function(e) {
268 | if(i == data.length - 1) {
269 | $rootScope.$apply(function(){
270 | d.resolve(e.target.result);
271 | });
272 | }
273 | };
274 | });
275 | } else {
276 | req = store.put(data);
277 | req.onsuccess = req.onerror = function(e) {
278 | $rootScope.$apply(function(){
279 | d.resolve(e.target.result);
280 | });
281 | };
282 | }
283 | return d.promise;
284 | });
285 | },
286 | /**
287 | * @ngdoc method
288 | * @name ObjectStore.delete
289 | * @function
290 | *
291 | * @description wrapper for IDBObjectStore.delete.
292 | * deletes the value for the specified primary key
293 | *
294 | * @params {any value} key primary key to indetify a value
295 | * @returns {object} $q.promise a promise on successfull execution
296 | */
297 | "delete": function(key) {
298 | var d = $q.defer();
299 | return this.internalObjectStore(this.storeName, READWRITE).then(function(store){
300 | var req = store.delete(key);
301 | req.onsuccess = req.onerror = function(e) {
302 | $rootScope.$apply(function(){
303 | d.resolve(e.target.result);
304 | });
305 | };
306 | return d.promise;
307 | });
308 | },
309 | /**
310 | * @ngdoc method
311 | * @name ObjectStore.clear
312 | * @function
313 | *
314 | * @description wrapper for IDBObjectStore.clear.
315 | * removes all data in an objectstore
316 | *
317 | * @returns {object} $q.promise a promise on successfull execution
318 | */
319 | "clear": function() {
320 | var d = $q.defer();
321 | return this.internalObjectStore(this.storeName, READWRITE).then(function(store){
322 | var req = store.clear();
323 | req.onsuccess = req.onerror = function(e) {
324 | $rootScope.$apply(function(){
325 | d.resolve(e.target.result);
326 | });
327 | };
328 | return d.promise;
329 | });
330 | },
331 | /**
332 | * @ngdoc method
333 | * @name ObjectStore.count
334 | * @function
335 | *
336 | * @description wrapper for IDBObjectStore.count.
337 | * returns the number of values in the objectstore, as a promise
338 | *
339 | * @returns {object} $q.promise a promise on successfull execution
340 | */
341 | "count": function() {
342 | return this.internalObjectStore(this.storeName, READONLY).then(function(store){
343 | return store.count();
344 | });
345 | },
346 | /**
347 | * @ngdoc method
348 | * @name ObjectStore.find
349 | * @function
350 | *
351 | * @description wrapper for IDBObjectStore.get and IDBIndex.get.
352 | * retrieves a single value with specified key, or index-key
353 | *
354 | * @params {any value} keyOrIndex the key to value, or an indexName
355 | * @params {any value} key the key of an index (*optional*)
356 | * @returns {any value} value ...wrapped in a promise
357 | */
358 | "find": function(keyOrIndex, keyIfIndex){
359 | var d = $q.defer();
360 | var promise = d.promise;
361 | return this.internalObjectStore(this.storeName, READONLY).then(function(store){
362 | var req;
363 |
364 | if(keyIfIndex) {
365 | req = store.index(keyOrIndex).get(keyIfIndex);
366 | } else {
367 | req = store.get(keyOrIndex);
368 | }
369 | req.onsuccess = req.onerror = function(e) {
370 | $rootScope.$apply(function(){
371 | d.resolve(e.target.result);
372 | });
373 | };
374 | return promise;
375 | });
376 | },
377 | /**
378 | * @ngdoc method
379 | * @name ObjectStore.getAll
380 | * @function
381 | *
382 | * @description wrapper for IDBObjectStore.getAll (or shim).
383 | * retrieves all values from objectstore using IDBObjectStore.getAll
384 | * or a cursor request if getAll is not implemented
385 | *
386 | * @returns {array} values ...wrapped in a promise
387 | */
388 | "getAll": function() {
389 | var results = [], d = $q.defer();
390 | return this.internalObjectStore(this.storeName, READONLY).then(function(store){
391 | var req;
392 | if (store.getAll) {
393 | req = store.getAll();
394 | req.onsuccess = req.onerror = function(e) {
395 | $rootScope.$apply(function(){
396 | d.resolve(e.target.result);
397 | });
398 | };
399 | } else {
400 | req = store.openCursor();
401 | req.onsuccess = function(e) {
402 | var cursor = e.target.result;
403 | if(cursor){
404 | results.push(cursor.value);
405 | cursor.continue();
406 | } else {
407 | $rootScope.$apply(function(){
408 | d.resolve(results);
409 | });
410 | }
411 | };
412 | req.onerror = function(e) {
413 | d.reject(e.target.result);
414 | };
415 | }
416 | return d.promise;
417 | });
418 | },
419 | /**
420 | * @ngdoc method
421 | * @name ObjectStore.each
422 | * @function
423 | *
424 | * @description wrapper for IDBObjectStore.openCursor or IDBIndex.openCursor.
425 | * returns a promise that is resolved when the cursor reaches an end.
426 | * On every "onsuccess" event of the cursor, the callback function is called, passing the cursor itself
427 | * https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB#Using_a_cursor
428 | *
429 | * @params {Function} onsuccessCallback the callback which runs when the onsuccess event is triggered
430 | * @params {object} options optional query parameters, see defaultQueryOptions
431 | * and QueryBuilder for details
432 | * @returns {object} IDBCursor ...wrapped in a promise
433 | */
434 | "each": function(callback, options){
435 | var d = $q.defer();
436 | return this.internalObjectStore(this.storeName, READWRITE).then(function(store){
437 | var req;
438 | options = options || defaultQueryOptions;
439 | if(options.useIndex) {
440 | req = store.index(options.useIndex).openCursor(options.keyRange, options.direction);
441 | } else {
442 | req = store.openCursor(options.keyRange, options.direction);
443 | }
444 | req.onsuccess = req.onerror = function(e) {
445 | $rootScope.$apply(function(){
446 | if(!e.target.result){
447 | d.resolve(e.target.result);
448 | }
449 | callback(e.target.result);
450 | });
451 | };
452 | return d.promise;
453 | });
454 | }
455 | };
456 |
457 | /**
458 | * @ngdoc object
459 | * @name QueryBuilder
460 | * @function
461 | *
462 | * @description utility object to easily create IDBKeyRange for cursor queries
463 | */
464 | var QueryBuilder = function() {
465 | this.result = defaultQueryOptions;
466 | };
467 | QueryBuilder.prototype = {
468 | /**
469 | * @ngdoc method
470 | * @name QueryBuilder.$lt
471 | * @function
472 | *
473 | * @description set an upper bound, e.g. A < value, excluding value
474 | *
475 | * @params {any value} value bound value
476 | * @returns {object} this QueryBuilder, for chaining params
477 | */
478 | "$lt": function(value) {
479 | this.result.keyRange = IDBKeyRange.upperBound(value, true);
480 | return this;
481 | },
482 | /**
483 | * @ngdoc method
484 | * @name QueryBuilder.$gt
485 | * @function
486 | *
487 | * @description set a lower bound, e.g. A > value, excluding value
488 | *
489 | * @params {any value} value bound value
490 | * @returns {object} this QueryBuilder, for chaining params
491 | */
492 | "$gt": function(value) {
493 | this.result.keyRange = IDBKeyRange.lowerBound(value, true);
494 | return this;
495 | },
496 | /**
497 | * @ngdoc method
498 | * @name QueryBuilder.$lte
499 | * @function
500 | *
501 | * @description set an upper bound, e.g. A <= value, including value
502 | *
503 | * @params {any value} value bound value
504 | * @returns {object} this QueryBuilder, for chaining params
505 | */
506 | "$lte": function(value) {
507 | this.result.keyRange = IDBKeyRange.upperBound(value);
508 | return this;
509 | },
510 | /**
511 | * @ngdoc method
512 | * @name QueryBuilder.$gte
513 | * @function
514 | *
515 | * @description set an upper bound, e.g. A >= value, including value
516 | *
517 | * @params {any value} value bound value
518 | * @returns {object} this QueryBuilder, for chaining params
519 | */
520 | "$gte": function(value) {
521 | this.result.keyRange = IDBKeyRange.lowerBound(value);
522 | return this;
523 | },
524 | /**
525 | * @ngdoc method
526 | * @name QueryBuilder.$eq
527 | * @function
528 | *
529 | * @description exact match, e.g. A = value
530 | *
531 | * @params {any value} value bound value
532 | * @returns {object} this QueryBuilder, for chaining params
533 | */
534 | "$eq": function(value) {
535 | this.result.keyRange = IDBKeyRange.only(value);
536 | return this;
537 | },
538 | /**
539 | * @ngdoc method
540 | * @name QueryBuilder.$between
541 | * @function
542 | *
543 | * @description set an upper and lower bound, e.g. low >= value <= hi,
544 | * optionally including value
545 | *
546 | * @params {any value} lowValue lower bound value
547 | * @params {any value} hiValue upper bound value
548 | * @params {boolean} exLow optional, exclude lower bound value
549 | * @params {boolean} exHi optional, exclude upper bound value
550 | * @returns {object} this QueryBuilder, for chaining params
551 | */
552 | "$between": function(lowValue, hiValue, exLow, exHi) {
553 | this.result.keyRange = IDBKeyRange.bound(lowValue,hiValue,exLow||false,exHi||false);
554 | return this;
555 | },
556 | /**
557 | * @ngdoc method
558 | * @name QueryBuilder.$asc
559 | * @function
560 | *
561 | * @description set the direction of traversal to ascending (natural)
562 | *
563 | * @params {boolean} unique return only distinct values, skipping
564 | * duplicates (*optional*)
565 | * @returns {object} this QueryBuilder, for chaining params
566 | */
567 | "$asc": function(unique) {
568 | this.result.order = (unique)? NEXTUNIQUE: NEXT;
569 | return this;
570 | },
571 | /**
572 | * @ngdoc method
573 | * @name QueryBuilder.$desc
574 | * @function
575 | *
576 | * @description set the direction of traversal to descending order
577 | *
578 | * @params {boolean} unique return only distinct values, skipping
579 | * duplicates (*optional*)
580 | * @returns {object} this QueryBuilder, for chaining params
581 | */
582 | "$desc": function(unique) {
583 | this.result.order = (unique)? PREVUNIQUE: PREV;
584 | return this;
585 | },
586 | /**
587 | * @ngdoc method
588 | * @name QueryBuilder.$index
589 | * @function
590 | *
591 | * @description optionally specify an index to use
592 | *
593 | * @params {string} indexName index to use
594 | * @returns {object} this QueryBuilder, for chaining params
595 | */
596 | "$index": function(indexName) {
597 | this.result.useIndex = indexName;
598 | return this;
599 | },
600 | /**
601 | * @ngdoc method
602 | * @name QueryBuilder.compile
603 | * @function
604 | *
605 | * @description returns an object to be passed to ObjectStore.each
606 | * @returns {object} queryOptions
607 | */
608 | "compile": function() {
609 | return this.result;
610 | }
611 | };
612 |
613 | /**
614 | * @ngdoc angular.$provider
615 | * @name $indexedDB
616 | * @function
617 | *
618 | * @description indexedDB provider object
619 | */
620 | return {
621 | /**
622 | * @ngdoc method
623 | * @name $indexedDB.objectStore
624 | * @function
625 | *
626 | * @description an IDBObjectStore to use
627 | *
628 | * @params {string} storename the name of the objectstore to use
629 | * @returns {object} ObjectStore
630 | */
631 | "objectStore": function(storeName) {
632 | return new ObjectStore(storeName);
633 | },
634 | /**
635 | * @ngdoc method
636 | * @name $indexedDB.dbInfo
637 | * @function
638 | *
639 | * @description statistical information about the current database
640 | * - database name and version
641 | * - objectstores in in database with name, value count, keyPath,
642 | * autoincrement flag and current assigned indices
643 | *
644 | * @returns {object} DBInfo
645 | */
646 | "dbInfo": function() {
647 | var storeNames, stores = [], tx, store;
648 | return dbPromise().then(function(db){
649 | storeNames = Array.prototype.slice.apply(db.objectStoreNames);
650 | tx = db.transaction(storeNames, READONLY);
651 | storeNames.forEach(function(storeName){
652 | store = tx.objectStore(storeName);
653 | stores.push({
654 | name: storeName,
655 | keyPath: store.keyPath,
656 | autoIncrement: store.autoIncrement,
657 | count: store.count(),
658 | indices: Array.prototype.slice.apply(store.indexNames)
659 | });
660 | });
661 | return {
662 | name: db.name,
663 | version: db.version,
664 | objectStores: stores
665 | };
666 | });
667 | },
668 | /**
669 | * @ngdoc method
670 | * @name $indexedDB.close
671 | * @function
672 | *
673 | * @description closes the current active database
674 | * @returns {object} this
675 | */
676 | "closeDB": function() {
677 | dbPromise().then(function(db){
678 | db.close();
679 | });
680 |
681 | module.db = null;
682 | module.dbPromise = null;
683 |
684 | return this;
685 | },
686 | /**
687 | * @ngdoc method
688 | * @name $indexedDB.switchDB
689 | * @function
690 | *
691 | * @description closes the current active database and opens another one
692 | *
693 | * @params {string} databaseName the name of the database to use
694 | * @params {number} version the version number of the database
695 | * @params {Function} upgradeCallBack the callback which proceeds the upgrade
696 | * @returns {object} this
697 | */
698 | "switchDB": function(databaseName, version, upgradeCallback) {
699 | this.closeDB();
700 | module.dbName = databaseName;
701 | module.dbVersion = version || 1;
702 | module.upgradeCallback = upgradeCallback || function() {};
703 | return this;
704 | },
705 | /**
706 | * @ngdoc method
707 | * @name $indexedDB.queryBuilder
708 | * @function
709 | *
710 | * @description provides access to the QueryBuilder utility
711 | *
712 | * @returns {object} QueryBuilder
713 | */
714 | "queryBuilder": function() {
715 | return new QueryBuilder();
716 | }
717 | };
718 | }];
719 | });
720 |
--------------------------------------------------------------------------------