Skip to content

Instantly share code, notes, and snippets.

Created August 15, 2012 17:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3361666 to your computer and use it in GitHub Desktop.
Save anonymous/3361666 to your computer and use it in GitHub Desktop.
"upgradeneeded" shim for Chrome's IndexedDB
<!DOCTYPE html>
<title>upgradeneeded shim test - basics</title>
<body>
<script src="upgradeneeded.js"></script>
<script>
window.indexedDB = window.indexedDB || window.webkitIndexedDB;
function show(s) {
document.querySelector('#output').appendChild(document.createTextNode(s + "\n"));
}
var dbname = "db" + Date.now();
doFirstOpen();
function doFirstOpen() {
var request = indexedDB.open(dbname, 1);
request.onerror = function(e) { show("error event: " + e); };
request.onblocked = function(e) { show("blocked event: " + e); };
request.onupgradeneeded = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("e.oldVersion: " + e.oldVersion);
show("e.newVersion: " + e.newVersion);
show("request.result: " + request.result);
show("request.result.version: " + request.result.version);
show("");
};
request.onsuccess = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("request.result: " + request.result);
show("");
request.result.close();
doSecondOpen();
};
}
function doSecondOpen() {
var request = indexedDB.open(dbname, 2);
request.onerror = function(e) { show("error event: " + e); };
request.onblocked = function(e) { show("blocked event: " + e); };
request.onupgradeneeded = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("e.oldVersion: " + e.oldVersion);
show("e.newVersion: " + e.newVersion);
show("request.result: " + request.result);
show("request.result.version: " + request.result.version);
show("");
};
request.onsuccess = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("request.result: " + request.result);
show("");
request.result.close();
};
}
</script>
<pre id="output"></pre>
</body>
<!DOCTYPE html>
<title>upgradeneeded shim test - listeners</title>
<body>
<script src="upgradeneeded.js"></script>
<script>
window.indexedDB = window.indexedDB || window.webkitIndexedDB;
function show(s) {
document.querySelector('#output').appendChild(document.createTextNode(s + "\n"));
}
var dbname = "db" + Date.now();
var request = indexedDB.open(dbname, 1);
request.onerror = function(e) { show("onerror handler: " + e); };
request.onblocked = function(e) { show("onblocked handler: " + e); };
request.onupgradeneeded = function(e) { show("onupgradeneeded handler: " + e.type); };
request.addEventListener('upgradeneeded', function(e) { show("upgradeneeded listener1: " + e.type); });
request.addEventListener('upgradeneeded', function(e) { show("upgradeneeded listener2: " + e.type); });
request.onsuccess = function(e) { show("onsuccess handler: " + e.type); };
request.addEventListener('success', function(e) { show("success listener1: " + e.type); });
request.addEventListener('success', function(e) { show("success listener1: " + e.type); });
var f = function(e) { show("SHOULD NOT BE CALLED"); };
request.removeEventListener("success", f);
request.addEventListener("success", f);
request.removeEventListener("success", f);
</script>
<pre id="output"></pre>
</body>
<!DOCTYPE html>
<title>upgradeneeded shim test - no version specified</title>
<body>
<script src="upgradeneeded.js"></script>
<script>
window.indexedDB = window.indexedDB || window.webkitIndexedDB;
function show(s) {
document.querySelector('#output').appendChild(document.createTextNode(s + "\n"));
}
var dbname = "db" + Date.now();
var request = indexedDB.open(dbname);
request.onerror = function(e) { show("error event: " + e); };
request.onblocked = function(e) { show("blocked event: " + e); };
request.onupgradeneeded = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("e.oldVersion: " + e.oldVersion);
show("e.newVersion: " + e.newVersion);
show("request.result: " + request.result);
show("request.result.version: " + request.result.version);
show("");
};
request.onsuccess = function(e) {
show("event: " + e);
show("event type: " + e.type);
show("events match? " + (e === window.event));
show("request.result: " + request.result);
show("");
};
</script>
<pre id="output"></pre>
</body>
if (!('onupgradeneeded' in webkitIndexedDB.open('feature-detect'))) {
var originalOpen = webkitIndexedDB.open;
webkitIndexedDB.open = function(name, version) {
if (arguments.length >= 2) {
version = Math.floor(Number(version));
if (version < 1 || version >= Math.pow(2,53)) {
throw new TypeError("Invalid version");
}
}
var shimRequest = (function() {
var eventListeners = Object.create(null);
return {
result: undefined,
error: null,
source: null,
transaction: null,
readyState: 'pending',
onsuccess: null,
onerror: null,
onblocked: null,
onupgradeneeded: null,
addEventListener: function(type, callback) {
eventListeners[type] = eventListeners[type] || [];
if (eventListeners[type].indexOf(callback) === -1) {
eventListeners[type].push(callback);
}
},
removeEventListener: function(type, callback) {
if (!(type in eventListeners)) { return; }
var index = eventListeners[type].indexOf(callback);
if (index !== -1) {
eventListeners[type].splice(index, 1);
}
},
dispatchEvent: function(event) {
var type = String(event.type),
oldSelfEvent = self.event;
try {
self.event = event;
if (typeof this['on' + type] === 'function') {
try { this['on' + type](event); } catch (e) { console.error(e); }
}
if (type in eventListeners) {
eventListeners[type].forEach(function(listener) {
try { listener(event); } catch (e) { console.error(e); }
});
}
} finally {
self.event = oldSelfEvent;
}
}
};
}());
function fire(type, target, properties) {
var event = new Event(type);
event.target = target;
if (properties) {
Object.keys(properties).forEach(function(key) {
event[key] = properties[key];
});
}
target.dispatchEvent(event);
}
var openIDBRequest = originalOpen.call(webkitIndexedDB, name);
openIDBRequest.addEventListener('error', function(e) {
shimRequest.result = openIDBRequest.result;
shimRequest.readyState = 'done';
shimRequest.error = e.target.error;
fire('error', shimRequest);
});
openIDBRequest.addEventListener('success', function () {
var db = openIDBRequest.result,
oldVersion = db.version;
if (!version && oldVersion === "") {
version = 1;
}
if (version < Number(db.version)) {
shimRequest.readyState = 'done';
shimRequest.error = {
name: 'VersionError',
code: 0,
message: 'An attempt was made to open a database using a lower version than the existing version.'
};
fire('error', shimRequest);
} else if (version === Number(db.version)) {
shimRequest.result = db;
shimRequest.readyState = 'done';
shimRequest.transaction = null;
fire('success', shimRequest);
} else {
var versionChangeIDBRequest = db.setVersion(version);
versionChangeIDBRequest.addEventListener('error', function(e) {
shimRequest.readyState = 'done';
shimRequest.error = e.target.error;
fire('error', shimRequest);
});
versionChangeIDBRequest.addEventListener('blocked', function() {
fire('blocked', shimRequest);
});
versionChangeIDBRequest.addEventListener('success', function() {
var trans = versionChangeIDBRequest.result;
shimRequest.result = db;
shimRequest.transaction = trans;
trans.addEventListener('abort', function(e) {
db.close();
shimRequest.readyState = 'done';
shimRequest.error = e.target.error;
fire('error', shimRequest);
});
trans.addEventListener('complete', function() {
shimRequest.result = db;
shimRequest.readyState = 'done';
shimRequest.transaction = null;
fire('success', shimRequest);
});
fire('upgradeneeded', shimRequest,
{oldVersion: oldVersion, newVersion: db.version});
});
}
});
return shimRequest;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment