diff --git a/CHANGELOG b/CHANGELOG index 65bc31f..e12c72a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +1.6.1 / 2015-11-07 +------------------ +* Make implementation preference configurable, don't prefer shim by default +* For the full changelog, please see here: https://github.com/jensarps/IDBWrapper/compare/v1.6.0...v1.6.1 + + 1.6.0 / 2015-10-05 ------------------ * Remove support for old Firefox browsers without autoIncrement diff --git a/bower.json b/bower.json index d7bb479..03ba68c 100644 --- a/bower.json +++ b/bower.json @@ -2,6 +2,6 @@ "name": "idbwrapper", "description": "A cross-browser wrapper for IndexedDB", "main": "idbstore.js", - "version": "1.6.0", + "version": "1.6.1", "dependencies": {} } diff --git a/idbstore.js b/idbstore.js index 2af31ab..01bf4c9 100644 --- a/idbstore.js +++ b/idbstore.js @@ -2,7 +2,7 @@ /** * @license IDBWrapper - A cross-browser wrapper for IndexedDB - * Version 1.6.0 + * Version 1.6.1 * Copyright (c) 2011 - 2015 Jens Arps * http://jensarps.de/ * @@ -35,7 +35,13 @@ onStoreReady: function () { }, onError: defaultErrorHandler, - indexes: [] + indexes: [], + implementationPreference: [ + 'indexedDB', + 'webkitIndexedDB', + 'mozIndexedDB', + 'shimIndexedDB' + ] }; /** @@ -44,7 +50,7 @@ * * @constructor * @name IDBStore - * @version 1.6.0 + * @version 1.6.1 * * @param {Object} [kwArgs] An options object used to configure the store and * set callbacks @@ -73,6 +79,7 @@ * @param {String} [kwArgs.indexes.indexData.keyPath] The key path of the index * @param {Boolean} [kwArgs.indexes.indexData.unique] Whether the index is unique * @param {Boolean} [kwArgs.indexes.indexData.multiEntry] Whether the index is multi entry + * @param {Array} [kwArgs.implementationPreference=['indexedDB','webkitIndexedDB','mozIndexedDB','shimIndexedDB']] An array of strings naming implementations to be used, in order or preference * @param {Function} [onStoreReady] A callback to be called when the store * is ready to be used. * @example @@ -116,7 +123,11 @@ onStoreReady && (this.onStoreReady = onStoreReady); var env = typeof window == 'object' ? window : self; - this.idb = env.shimIndexedDB || env.indexedDB || env.webkitIndexedDB || env.mozIndexedDB; + var availableImplementations = this.implementationPreference.filter(function (implName) { + return implName in env; + }); + this.implementation = availableImplementations[0]; + this.idb = env[this.implementation]; this.keyRange = env.IDBKeyRange || env.webkitIDBKeyRange || env.mozIDBKeyRange; this.consts = { @@ -137,21 +148,22 @@ /** * A pointer to the IDBStore ctor * - * @type IDBStore + * @private + * @type {Function} */ constructor: IDBStore, /** * The version of IDBStore * - * @type String + * @type {String} */ - version: '1.6.0', + version: '1.6.1', /** * A reference to the IndexedDB object * - * @type Object + * @type {Object} */ db: null, @@ -159,63 +171,77 @@ * The full name of the IndexedDB used by IDBStore, composed of * this.storePrefix + this.storeName * - * @type String + * @type {String} */ dbName: null, /** * The version of the IndexedDB used by IDBStore * - * @type Number + * @type {Number} */ dbVersion: null, /** * A reference to the objectStore used by IDBStore * - * @type Object + * @type {Object} */ store: null, /** * The store name * - * @type String + * @type {String} */ storeName: null, /** * The prefix to prepend to the store name * - * @type String + * @type {String} */ storePrefix: null, /** * The key path * - * @type String + * @type {String} */ keyPath: null, /** * Whether IDBStore uses autoIncrement * - * @type Boolean + * @type {Boolean} */ autoIncrement: null, /** * The indexes used by IDBStore * - * @type Array + * @type {Array} */ indexes: null, + /** + * The implemantations to try to use, in order of preference + * + * @type {Array} + */ + implementationPreference: null, + + /** + * The actual implementation being used + * + * @type {String} + */ + implementation: '', + /** * The callback to be called when the store is ready to be used * - * @type Function + * @type {Function} */ onStoreReady: null, @@ -223,14 +249,14 @@ * The callback to be called if an error occurred during instantiation * of the store * - * @type Function + * @type {Function} */ onError: null, /** * The internal insertID counter * - * @type Number + * @type {Number} * @private */ _insertIdCount: 0, @@ -289,7 +315,7 @@ if(!this.db.objectStoreNames.contains(this.storeName)){ // We should never ever get here. // Lets notify the user anyway. - this.onError(new Error('Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser.')); + this.onError(new Error('Object store couldn\'t be created.')); return; } diff --git a/idbstore.min.js b/idbstore.min.js index 499d735..5438a94 100644 --- a/idbstore.min.js +++ b/idbstore.min.js @@ -1,30 +1,30 @@ /* IDBWrapper - A cross-browser wrapper for IndexedDB - Version 1.6.0 + Version 1.6.1 Copyright (c) 2011 - 2015 Jens Arps http://jensarps.de/ Licensed under the MIT (X11) license */ -(function(h,i,l){"function"===typeof define?define(i):"undefined"!==typeof module&&module.exports?module.exports=i():l[h]=i()})("IDBStore",function(){var h=function(a){throw a;},i=function(){},l={storeName:"Store",storePrefix:"IDBWrapper-",dbVersion:1,keyPath:"id",autoIncrement:!0,onStoreReady:function(){},onError:h,indexes:[]},j=function(a,c){"undefined"==typeof c&&"function"==typeof a&&(c=a);"[object Object]"!=Object.prototype.toString.call(a)&&(a={});for(var b in l)this[b]="undefined"!=typeof a[b]? -a[b]:l[b];this.dbName=this.storePrefix+this.storeName;this.dbVersion=parseInt(this.dbVersion,10)||1;c&&(this.onStoreReady=c);b="object"==typeof window?window:self;this.idb=b.shimIndexedDB||b.indexedDB||b.webkitIndexedDB||b.mozIndexedDB;this.keyRange=b.IDBKeyRange||b.webkitIDBKeyRange||b.mozIDBKeyRange;this.consts={READ_ONLY:"readonly",READ_WRITE:"readwrite",VERSION_CHANGE:"versionchange",NEXT:"next",NEXT_NO_DUPLICATE:"nextunique",PREV:"prev",PREV_NO_DUPLICATE:"prevunique"};this.openDB()};j.prototype= -{constructor:j,version:"1.6.0",db:null,dbName:null,dbVersion:null,store:null,storeName:null,storePrefix:null,keyPath:null,autoIncrement:null,indexes:null,onStoreReady:null,onError:null,_insertIdCount:0,openDB:function(){var a=this.idb.open(this.dbName,this.dbVersion),c=!1;a.onerror=function(b){var a=!1;"error"in b.target?a="VersionError"==b.target.error.name:"errorCode"in b.target&&(a=12==b.target.errorCode);if(a)this.onError(Error("The version number provided is lower than the existing one."));else this.onError(b)}.bind(this); -a.onsuccess=function(a){if(!c)if(this.db)this.onStoreReady();else if(this.db=a.target.result,"string"==typeof this.db.version)this.onError(Error("The IndexedDB implementation in this browser is outdated. Please upgrade your browser."));else if(this.db.objectStoreNames.contains(this.storeName)){this.store=this.db.transaction([this.storeName],this.consts.READ_ONLY).objectStore(this.storeName);var d=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(a){var b=a.name;b?(this.normalizeIndexData(a), -this.hasIndex(b)?(this.indexComplies(this.store.index(b),a)||(c=!0,this.onError(Error('Cannot modify index "'+b+'" for current version. Please bump version number to '+(this.dbVersion+1)+"."))),d.splice(d.indexOf(b),1)):(c=!0,this.onError(Error('Cannot create new index "'+b+'" for current version. Please bump version number to '+(this.dbVersion+1)+".")))):(c=!0,this.onError(Error("Cannot create index: No index name given.")))},this);d.length&&(c=!0,this.onError(Error('Cannot delete index(es) "'+d.toString()+ -'" for current version. Please bump version number to '+(this.dbVersion+1)+".")));c||this.onStoreReady()}else this.onError(Error("Something is wrong with the IndexedDB implementation in this browser. Please upgrade your browser."))}.bind(this);a.onupgradeneeded=function(a){this.db=a.target.result;if(this.db.objectStoreNames.contains(this.storeName))this.store=a.target.transaction.objectStore(this.storeName);else{a={autoIncrement:this.autoIncrement};if(null!==this.keyPath)a.keyPath=this.keyPath;this.store= -this.db.createObjectStore(this.storeName,a)}var d=Array.prototype.slice.call(this.getIndexList());this.indexes.forEach(function(a){var b=a.name;b||(c=!0,this.onError(Error("Cannot create index: No index name given.")));this.normalizeIndexData(a);this.hasIndex(b)?(this.indexComplies(this.store.index(b),a)||(this.store.deleteIndex(b),this.store.createIndex(b,a.keyPath,{unique:a.unique,multiEntry:a.multiEntry})),d.splice(d.indexOf(b),1)):this.store.createIndex(b,a.keyPath,{unique:a.unique,multiEntry:a.multiEntry})}, -this);d.length&&d.forEach(function(a){this.store.deleteIndex(a)},this)}.bind(this)},deleteDatabase:function(a,c){if(this.idb.deleteDatabase){this.db.close();var b=this.idb.deleteDatabase(this.dbName);b.onsuccess=a;b.onerror=c}else c(Error("Browser does not support IndexedDB deleteDatabase!"))},put:function(a,c,b,d){null!==this.keyPath&&(d=b,b=c,c=a);d||(d=h);b||(b=i);var e=!1,f=null,g=this.db.transaction([this.storeName],this.consts.READ_WRITE);g.oncomplete=function(){(e?b:d)(f)};g.onabort=d;g.onerror= -d;null!==this.keyPath?(this._addIdPropertyIfNeeded(c),a=g.objectStore(this.storeName).put(c)):a=g.objectStore(this.storeName).put(c,a);a.onsuccess=function(a){e=!0;f=a.target.result};a.onerror=d;return g},get:function(a,c,b){b||(b=h);c||(c=i);var d=!1,e=null,f=this.db.transaction([this.storeName],this.consts.READ_ONLY);f.oncomplete=function(){(d?c:b)(e)};f.onabort=b;f.onerror=b;a=f.objectStore(this.storeName).get(a);a.onsuccess=function(a){d=!0;e=a.target.result};a.onerror=b;return f},remove:function(a, -c,b){b||(b=h);c||(c=i);var d=!1,e=null,f=this.db.transaction([this.storeName],this.consts.READ_WRITE);f.oncomplete=function(){(d?c:b)(e)};f.onabort=b;f.onerror=b;a=f.objectStore(this.storeName)["delete"](a);a.onsuccess=function(a){d=!0;e=a.target.result};a.onerror=b;return f},batch:function(a,c,b){b||(b=h);c||(c=i);if("[object Array]"!=Object.prototype.toString.call(a))b(Error("dataArray argument must be of type Array."));else if(0===a.length)return c(!0);var d=this.db.transaction([this.storeName], -this.consts.READ_WRITE);d.oncomplete=function(){(g?c:b)(g)};d.onabort=b;d.onerror=b;var e=a.length,f=!1,g=!1,k=function(){e--;0===e&&!f&&(g=f=!0)};a.forEach(function(a){var c=a.type,e=a.key,g=a.value,a=function(a){d.abort();f||(f=!0,b(a,c,e))};if("remove"==c)g=d.objectStore(this.storeName)["delete"](e),g.onsuccess=k,g.onerror=a;else if("put"==c)null!==this.keyPath?(this._addIdPropertyIfNeeded(g),g=d.objectStore(this.storeName).put(g)):g=d.objectStore(this.storeName).put(g,e),g.onsuccess=k,g.onerror= -a},this);return d},putBatch:function(a,c,b){return this.batch(a.map(function(a){return{type:"put",value:a}}),c,b)},upsertBatch:function(a,c,b,d){"function"==typeof c&&(d=b=c,c={});d||(d=h);b||(b=i);c||(c={});"[object Array]"!=Object.prototype.toString.call(a)&&d(Error("dataArray argument must be of type Array."));var e=this.db.transaction([this.storeName],this.consts.READ_WRITE);e.oncomplete=function(){m?b(a):d(!1)};e.onabort=d;e.onerror=d;var f=c.keyField||this.keyPath,g=a.length,k=!1,m=!1,j=0,o= -function(b){a[j++][f]=b.target.result;g--;0===g&&!k&&(m=k=!0)};a.forEach(function(a){var b=a.key;null!==this.keyPath?(this._addIdPropertyIfNeeded(a),a=e.objectStore(this.storeName).put(a)):a=e.objectStore(this.storeName).put(a,b);a.onsuccess=o;a.onerror=function(a){e.abort();k||(k=!0,d(a))}},this);return e},removeBatch:function(a,c,b){return this.batch(a.map(function(a){return{type:"remove",key:a}}),c,b)},getBatch:function(a,c,b,d){b||(b=h);c||(c=i);d||(d="sparse");if("[object Array]"!=Object.prototype.toString.call(a))b(Error("keyArray argument must be of type Array.")); -else if(0===a.length)return c([]);var e=this.db.transaction([this.storeName],this.consts.READ_ONLY);e.oncomplete=function(){(k?c:b)(j)};e.onabort=b;e.onerror=b;var f=[],g=a.length,k=!1,j=null,l=function(a){a.target.result||"dense"==d?f.push(a.target.result):"sparse"==d&&f.length++;g--;0===g&&(k=!0,j=f)};a.forEach(function(a){a=e.objectStore(this.storeName).get(a);a.onsuccess=l;a.onerror=function(a){j=a;b(a);e.abort()}},this);return e},getAll:function(a,c){c||(c=h);a||(a=i);var b=this.db.transaction([this.storeName], -this.consts.READ_ONLY),d=b.objectStore(this.storeName);d.getAll?this._getAllNative(b,d,a,c):this._getAllCursor(b,d,a,c);return b},_getAllNative:function(a,c,b,d){var e=!1,f=null;a.oncomplete=function(){(e?b:d)(f)};a.onabort=d;a.onerror=d;a=c.getAll();a.onsuccess=function(a){e=!0;f=a.target.result};a.onerror=d},_getAllCursor:function(a,c,b,d){var e=[],f=!1,g=null;a.oncomplete=function(){(f?b:d)(g)};a.onabort=d;a.onerror=d;a=c.openCursor();a.onsuccess=function(a){(a=a.target.result)?(e.push(a.value), -a["continue"]()):(f=!0,g=e)};a.onError=d},clear:function(a,c){c||(c=h);a||(a=i);var b=!1,d=null,e=this.db.transaction([this.storeName],this.consts.READ_WRITE);e.oncomplete=function(){(b?a:c)(d)};e.onabort=c;e.onerror=c;var f=e.objectStore(this.storeName).clear();f.onsuccess=function(a){b=!0;d=a.target.result};f.onerror=c;return e},_addIdPropertyIfNeeded:function(a){"undefined"==typeof a[this.keyPath]&&(a[this.keyPath]=this._insertIdCount++ +Date.now())},getIndexList:function(){return this.store.indexNames}, -hasIndex:function(a){return this.store.indexNames.contains(a)},normalizeIndexData:function(a){a.keyPath=a.keyPath||a.name;a.unique=!!a.unique;a.multiEntry=!!a.multiEntry},indexComplies:function(a,c){return["keyPath","unique","multiEntry"].every(function(b){if("multiEntry"==b&&void 0===a[b]&&!1===c[b])return!0;if("keyPath"==b&&"[object Array]"==Object.prototype.toString.call(c[b])){var b=c.keyPath,d=a.keyPath;if("string"==typeof d)return b.toString()==d;if(!("function"==typeof d.contains||"function"== -typeof d.indexOf)||d.length!==b.length)return!1;for(var e=0,f=b.length;e