TheDJ has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/157818

Change subject: Add a jQuery promise lib around indexedDB
......................................................................

Add a jQuery promise lib around indexedDB

Added ed5507cd49ee93fbdec449341306b81507db8f41
of https://github.com/axemclion/jquery-indexeddb

Will use this to improve change: I38372e4ae38

Change-Id: I9b5ccc018ad19ae3abcc95e879e9c4a467533d71
---
M resources/Resources.php
A resources/lib/jquery/jquery.indexeddb.js
2 files changed, 548 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/18/157818/1

diff --git a/resources/Resources.php b/resources/Resources.php
index 3073152..827ef21 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -249,6 +249,9 @@
        'jquery.hoverIntent' => array(
                'scripts' => 'resources/lib/jquery/jquery.hoverIntent.js',
        ),
+       'jquery.indexeddb' => array(
+               'scripts' => 'resources/lib/jquery/jquery.indexeddb.js',
+       },
        'jquery.json' => array(
                // @deprecated since 1.24: Use the 'json' module and global 
JSON object instead.
                'scripts' => array(
diff --git a/resources/lib/jquery/jquery.indexeddb.js 
b/resources/lib/jquery/jquery.indexeddb.js
new file mode 100644
index 0000000..0001ed6
--- /dev/null
+++ b/resources/lib/jquery/jquery.indexeddb.js
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2012 Parashuram N and other contributors
+ * http://nparashuram.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+(function($, undefined) {
+       'use strict';
+       var indexedDB = window.indexedDB || window.mozIndexedDB || 
window.webkitIndexedDB || window.msIndexedDB;
+       var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
+       var IDBCursor = window.IDBCursor || window.webkitIDBCursor || {};
+       if (typeof IDBCursor.PREV === "undefined") {
+        IDBCursor.PREV = "prev";
+    }
+       if (typeof IDBCursor.NEXT === "undefined") {
+        IDBCursor.NEXT = "next";
+    }
+
+       /**
+        * Best to use the constant IDBTransaction since older version support 
numeric types while the latest spec
+        * supports strings
+        */
+       var IDBTransaction = window.IDBTransaction || 
window.webkitIDBTransaction;
+
+       function getDefaultTransaction(mode) {
+               var result = null;
+               switch (mode) {
+                       case 0:
+                       case 1:
+                       case "readwrite":
+                       case "readonly":
+                               result = mode;
+                               break;
+                       default:
+                               result = IDBTransaction.READ_WRITE || 
"readwrite";
+               }
+               return result;
+       }
+
+       $.extend({
+               /**
+                * The IndexedDB object used to open databases
+                * @param {Object} dbName - name of the database
+                * @param {Object} config - version, onupgradeneeded, 
onversionchange, schema
+                */
+               "indexedDB": function(dbName, config) {
+                       if (config) {
+                               // Parse the config argument
+                               if (typeof config === "number") config = {
+                                       "version": config
+                               };
+
+                               var version = config.version;
+                               if (config.schema && !version) {
+                                       var max = -1;
+                                       for (var key in config.schema) {
+                                               max = max > key ? max : key;
+                                       }
+                                       version = config.version || max;
+                               }
+                       }
+
+
+                       var wrap = {
+                               "request": function(req, args) {
+                                       return $.Deferred(function(dfd) {
+                                               try {
+                                                       var idbRequest = typeof 
req === "function" ? req(args) : req;
+                                                       idbRequest.onsuccess = 
function(e) {
+                                                               
+                                                               
dfd.resolveWith(idbRequest, [idbRequest.result, e]);
+                                                       };
+                                                       idbRequest.onerror = 
function(e) {
+                                                               
+                                                               
dfd.rejectWith(idbRequest, [idbRequest.error, e]);
+                                                       };
+                                                       if (typeof 
idbRequest.onblocked !== "undefined" && idbRequest.onblocked === null) {
+                                                               
idbRequest.onblocked = function(e) {
+                                                                       
+                                                                       var res;
+                                                                       try {
+                                                                               
res = idbRequest.result;
+                                                                       } catch 
(e) {
+                                                                               
res = null; // Required for Older Chrome versions, accessing result causes 
error 
+                                                                       }
+                                                                       
dfd.notifyWith(idbRequest, [res, e]);
+                                                               };
+                                                       }
+                                                       if (typeof 
idbRequest.onupgradeneeded !== "undefined" && idbRequest.onupgradeneeded === 
null) {
+                                                               
idbRequest.onupgradeneeded = function(e) {
+                                                                       
+                                                                       
dfd.notifyWith(idbRequest, [idbRequest.result, e]);
+                                                               };
+                                                       }
+                                               } catch (e) {
+                                                       e.name = "exception";
+                                                       
dfd.rejectWith(idbRequest, ["exception", e]);
+                                               }
+                                       });
+                               },
+                               // Wraps the IDBTransaction to return promises, 
and other dependent methods
+                               "transaction": function(idbTransaction) {
+                                       return {
+                                               "objectStore": 
function(storeName) {
+                                                       try {
+                                                               return 
wrap.objectStore(idbTransaction.objectStore(storeName));
+                                                       } catch (e) {
+                                                               
idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort();
+                                                               return 
wrap.objectStore(null);
+                                                       }
+                                               },
+                                               "createObjectStore": 
function(storeName, storeParams) {
+                                                       try {
+                                                               return 
wrap.objectStore(idbTransaction.db.createObjectStore(storeName, storeParams));
+                                                       } catch (e) {
+                                                               
idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort();
+                                                       }
+                                               },
+                                               "deleteObjectStore": 
function(storeName) {
+                                                       try {
+                                                               
idbTransaction.db.deleteObjectStore(storeName);
+                                                       } catch (e) {
+                                                               
idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort();
+                                                       }
+                                               },
+                                               "abort": function() {
+                                                       idbTransaction.abort();
+                                               }
+                                       };
+                               },
+                               "objectStore": function(idbObjectStore) {
+                                       var result = {};
+                                       // Define CRUD operations
+                                       var crudOps = ["add", "put", "get", 
"delete", "clear", "count"];
+                                       for (var i = 0; i < crudOps.length; 
i++) {
+                                               result[crudOps[i]] = 
(function(op) {
+                                                       return function() {
+                                                               return 
wrap.request(function(args) {
+                                                                       return 
idbObjectStore[op].apply(idbObjectStore, args);
+                                                               }, arguments);
+                                                       };
+                                               })(crudOps[i]);
+                                       }
+
+                                       result.each = function(callback, range, 
direction) {
+                                               return wrap.cursor(function() {
+                                                       if (direction) {
+                                                               return 
idbObjectStore.openCursor(wrap.range(range), direction);
+                                                       } else {
+                                                               return 
idbObjectStore.openCursor(wrap.range(range));
+                                                       }
+                                               }, callback);
+                                       };
+
+                                       result.index = function(name) {
+                                               return wrap.index(function() {
+                                                       return 
idbObjectStore.index(name);
+                                               });
+                                       };
+
+                                       result.createIndex = function(prop, 
options, indexName) {
+                                               if (arguments.length === 2 && 
typeof options === "string") {
+                                                       indexName = 
arguments[1];
+                                                       options = null;
+                                               }
+                                               if (!indexName) {
+                                                       indexName = prop;
+                                               }
+                                               return wrap.index(function() {
+                                                       return 
idbObjectStore.createIndex(indexName, prop, options);
+                                               });
+                                       };
+
+                                       result.deleteIndex = 
function(indexName) {
+                                               return 
idbObjectStore.deleteIndex(indexName);
+                                       };
+
+                                       return result;
+                               },
+
+                               "range": function(r) {
+                                       if ($.isArray(r)) {
+                                               if (r.length === 1) {
+                                                       return 
IDBKeyRange.only(r[0]);
+                                               } else {
+                                                       return 
IDBKeyRange.bound(r[0], r[1], (typeof r[2] === 'undefined') ? false : r[2], 
(typeof r[3] === 'undefined') ? false : r[3]);
+                                               }
+                                       } else if (typeof r === "undefined") {
+                                               return null;
+                                       } else {
+                                               return r;
+                                       }
+                               },
+
+                               "cursor": function(idbCursor, callback) {
+                                       return $.Deferred(function(dfd) {
+                                               try {
+                                                       
+                                                       var cursorReq = typeof 
idbCursor === "function" ? idbCursor() : idbCursor;
+                                                       cursorReq.onsuccess = 
function(e) {
+                                                               
+                                                               if 
(!cursorReq.result) {
+                                                                       
dfd.resolveWith(cursorReq, [null, e]);
+                                                                       return;
+                                                               }
+                                                               var elem = {
+                                                                       // 
Delete, update do not move 
+                                                                       
"delete": function() {
+                                                                               
return wrap.request(function() {
+                                                                               
        return cursorReq.result["delete"]();
+                                                                               
});
+                                                                       },
+                                                                       
"update": function(data) {
+                                                                               
return wrap.request(function() {
+                                                                               
        return cursorReq.result["update"](data);
+                                                                               
});
+                                                                       },
+                                                                       "next": 
function(key) {
+                                                                               
this.data = key;
+                                                                       },
+                                                                       "key": 
cursorReq.result.key,
+                                                                       
"value": cursorReq.result.value
+                                                               };
+                                                               
+                                                               
dfd.notifyWith(cursorReq, [elem, e]);
+                                                               var result = 
callback.apply(cursorReq, [elem]);
+                                                               
+                                                               try {
+                                                                       if 
(result === false) {
+                                                                               
dfd.resolveWith(cursorReq, [null, e]);
+                                                                       } else 
if (typeof result === "number") {
+                                                                               
cursorReq.result["advance"].apply(cursorReq.result, [result]);
+                                                                       } else {
+                                                                               
if (elem.data) cursorReq.result["continue"].apply(cursorReq.result, 
[elem.data]);
+                                                                               
else cursorReq.result["continue"]();
+                                                                       }
+                                                               } catch (e) {
+                                                                       
+                                                                       
dfd.rejectWith(cursorReq, [cursorReq.result, e]);
+                                                               }
+                                                       };
+                                                       cursorReq.onerror = 
function(e) {
+                                                               
+                                                               
dfd.rejectWith(cursorReq, [cursorReq.result, e]);
+                                                       };
+                                               } catch (e) {
+                                                       
+                                                       e.type = "exception";
+                                                       
dfd.rejectWith(cursorReq, [null, e]);
+                                               }
+                                       });
+                               },
+
+                               "index": function(index) {
+                                       try {
+                                               var idbIndex = (typeof index 
=== "function" ? index() : index);
+                                       } catch (e) {
+                                               idbIndex = null;
+                                       }
+                                       
+                                       return {
+                                               "each": function(callback, 
range, direction) {
+                                                       return 
wrap.cursor(function() {
+                                                               if (direction) {
+                                                                       return 
idbIndex.openCursor(wrap.range(range), direction);
+                                                               } else {
+                                                                       return 
idbIndex.openCursor(wrap.range(range));
+                                                               }
+
+                                                       }, callback);
+                                               },
+                                               "eachKey": function(callback, 
range, direction) {
+                                                       return 
wrap.cursor(function() {
+                                                               if (direction) {
+                                                                       return 
idbIndex.openKeyCursor(wrap.range(range), direction);
+                                                               } else {
+                                                                       return 
idbIndex.openKeyCursor(wrap.range(range));
+                                                               }
+                                                       }, callback);
+                                               },
+                                               "get": function(key) {
+                                                       if (typeof idbIndex.get 
=== "function") {
+                                                               return 
wrap.request(idbIndex.get(key));
+                                                       } else {
+                                                               return 
idbIndex.openCursor(wrap.range(key));
+                                                       }
+                                               },
+                                               "count": function() {
+                                                       if (typeof 
idbIndex.count === "function") {
+                                                               return 
wrap.request(idbIndex.count());
+                                                       } else {
+                                                               throw "Count 
not implemented for cursors";
+                                                       }
+                                               },
+                                               "getKey": function(key) {
+                                                       if (typeof 
idbIndex.getKey === "function") {
+                                                               return 
wrap.request(idbIndex.getKey(key));
+                                                       } else {
+                                                               return 
idbIndex.openKeyCursor(wrap.range(key));
+                                                       }
+                                               }
+                                       };
+                               }
+                       };
+
+
+                       // Start with opening the database
+                       var dbPromise = wrap.request(function() {
+                               
+                               return version ? indexedDB.open(dbName, 
parseInt(version)) : indexedDB.open(dbName);
+                       });
+                       dbPromise.then(function(db, e) {
+                               
+                               db.onversionchange = function() {
+                                       // Try to automatically close the 
database if there is a version change request
+                                       if (!(config && config.onversionchange 
&& config.onversionchange() !== false)) {
+                                               db.close();
+                                       }
+                               };
+                       }, function(error, e) {
+                               
+                               // Nothing much to do if an error occurs
+                       }, function(db, e) {
+                               if (e && e.type === "upgradeneeded") {
+                                       if (config && config.schema) {
+                                               // Assuming that version is 
always an integer 
+                                               
+                                               for (var i = e.oldVersion + 1; 
i <= e.newVersion; i++) {
+                                                       typeof config.schema[i] 
=== "function" && config.schema[i].call(this, 
wrap.transaction(this.transaction));
+                                               }
+                                       }
+                                       if (config && typeof config.upgrade === 
"function") {
+                                               config.upgrade.call(this, 
wrap.transaction(this.transaction));
+                                       }
+                               }
+                       });
+
+                       return $.extend(dbPromise, {
+                               "cmp": function(key1, key2) {
+                                       return indexedDB.cmp(key1, key2);
+                               },
+                               "deleteDatabase": function() {
+                                       // Kinda looks ugly coz DB is opened 
before it needs to be deleted. 
+                                       // Blame it on the API 
+                                       return $.Deferred(function(dfd) {
+                                               dbPromise.then(function(db, e) {
+                                                       db.close();
+                                                       wrap.request(function() 
{
+                                                               return 
indexedDB.deleteDatabase(dbName);
+                                                       
}).then(function(result, e) {
+                                                               
dfd.resolveWith(this, [result, e]);
+                                                       }, function(error, e) {
+                                                               
dfd.rejectWith(this, [error, e]);
+                                                       }, function(db, e) {
+                                                               
dfd.notifyWith(this, [db, e]);
+                                                       });
+                                               }, function(error, e) {
+                                                       dfd.rejectWith(this, 
[error, e]);
+                                               }, function(db, e) {
+                                                       dfd.notifyWith(this, 
[db, e]);
+                                               });
+                                       });
+                               },
+                               "transaction": function(storeNames, mode) {
+                                       !$.isArray(storeNames) && (storeNames = 
[storeNames]);
+                                       mode = getDefaultTransaction(mode);
+                                       return $.Deferred(function(dfd) {
+                                               dbPromise.then(function(db, e) {
+                                                       var idbTransaction;
+                                                       try {
+                                                               
+                                                               idbTransaction 
= db.transaction(storeNames, mode);
+                                                               
+                                                               
idbTransaction.onabort = idbTransaction.onerror = function(e) {
+                                                                       
dfd.rejectWith(idbTransaction, [e]);
+                                                               };
+                                                               
idbTransaction.oncomplete = function(e) {
+                                                                       
dfd.resolveWith(idbTransaction, [e]);
+                                                               };
+                                                       } catch (e) {
+                                                               
+                                                               e.type = 
"exception";
+                                                               
dfd.rejectWith(this, [e]);
+                                                               return;
+                                                       }
+                                                       try {
+                                                               
dfd.notifyWith(idbTransaction, [wrap.transaction(idbTransaction)]);
+                                                       } catch (e) {
+                                                               e.type = 
"exception";
+                                                               
dfd.rejectWith(this, [e]);
+                                                       }
+                                               }, function(err, e) {
+                                                       dfd.rejectWith(this, 
[e, err]);
+                                               }, function(res, e) {
+                                                       
+                                                       //dfd.notifyWith(this, 
["", e]);
+                                               });
+
+                                       });
+                               },
+                               "objectStore": function(storeName, mode) {
+                                       var me = this,
+                                               result = {};
+
+                                       function op(callback) {
+                                               return $.Deferred(function(dfd) 
{
+                                                       function 
onTransactionProgress(trans, callback) {
+                                                               try {
+                                                                       
+                                                                       
callback(trans.objectStore(storeName)).then(function(result, e) {
+                                                                               
dfd.resolveWith(this, [result, e]);
+                                                                       }, 
function(err, e) {
+                                                                               
dfd.rejectWith(this, [err, e]);
+                                                                       });
+                                                               } catch (e) {
+                                                                       
+                                                                       e.name 
= "exception";
+                                                                       
dfd.rejectWith(trans, [e, e]);
+                                                               }
+                                                       }
+                                                       
me.transaction(storeName, getDefaultTransaction(mode)).then(function() {
+                                                               
+                                                               // Nothing to 
do when transaction is complete
+                                                       }, function(err, e) {
+                                                               // If 
transaction fails, CrudOp fails
+                                                               if (err.code 
=== err.NOT_FOUND_ERR && (mode === true || typeof mode === "object")) {
+                                                                       
+                                                                       var db 
= this.result;
+                                                                       
db.close();
+                                                                       
dbPromise = wrap.request(function() {
+                                                                               
+                                                                               
return indexedDB.open(dbName, (parseInt(db.version, 10) || 1) + 1);
+                                                                       });
+                                                                       
dbPromise.then(function(db, e) {
+                                                                               
+                                                                               
db.onversionchange = function() {
+                                                                               
        // Try to automatically close the database if there is a version change 
request
+                                                                               
        if (!(config && config.onversionchange && config.onversionchange() !== 
false)) {
+                                                                               
                db.close();
+                                                                               
        }
+                                                                               
};
+                                                                               
me.transaction(storeName, getDefaultTransaction(mode)).then(function() {
+                                                                               
        
+                                                                               
        // Nothing much to do
+                                                                               
}, function(err, e) {
+                                                                               
        dfd.rejectWith(this, [err, e]);
+                                                                               
}, function(trans, e) {
+                                                                               
        
+                                                                               
        onTransactionProgress(trans, callback);
+                                                                               
});
+                                                                       }, 
function(err, e) {
+                                                                               
dfd.rejectWith(this, [err, e]);
+                                                                       }, 
function(db, e) {
+                                                                               
if (e.type === "upgradeneeded") {
+                                                                               
        try {
+                                                                               
                
+                                                                               
                db.createObjectStore(storeName, mode === true ? {
+                                                                               
                        "autoIncrement": true
+                                                                               
                } : mode);
+                                                                               
                
+                                                                               
        } catch (ex) {
+                                                                               
                
+                                                                               
                dfd.rejectWith(this, [ex, e]);
+                                                                               
        }
+                                                                               
}
+                                                                       });
+                                                               } else {
+                                                                       
dfd.rejectWith(this, [err, e]);
+                                                               }
+                                                       }, function(trans) {
+                                                               
+                                                               
onTransactionProgress(trans, callback);
+                                                       });
+                                               });
+                                       }
+
+                                       function crudOp(opName, args) {
+                                               return 
op(function(wrappedObjectStore) {
+                                                       return 
wrappedObjectStore[opName].apply(wrappedObjectStore, args);
+                                               });
+                                       }
+
+                                       function indexOp(opName, indexName, 
args) {
+                                               return 
op(function(wrappedObjectStore) {
+                                                       var index = 
wrappedObjectStore.index(indexName);
+                                                       return 
index[opName].apply(index[opName], args);
+                                               });
+                                       }
+
+                                       var crud = ["add", "delete", "get", 
"put", "clear", "count", "each"];
+                                       for (var i = 0; i < crud.length; i++) {
+                                               result[crud[i]] = (function(op) 
{
+                                                       return function() {
+                                                               return 
crudOp(op, arguments);
+                                                       };
+                                               })(crud[i]);
+                                       }
+
+                                       result.index = function(indexName) {
+                                               return {
+                                                       "each": 
function(callback, range, direction) {
+                                                               return 
indexOp("each", indexName, [callback, range, direction]);
+                                                       },
+                                                       "eachKey": 
function(callback, range, direction) {
+                                                               return 
indexOp("eachKey", indexName, [callback, range, direction]);
+                                                       },
+                                                       "get": function(key) {
+                                                               return 
indexOp("get", indexName, [key]);
+                                                       },
+                                                       "count": function() {
+                                                               return 
indexOp("count", indexName, []);
+                                                       },
+                                                       "getKey": function(key) 
{
+                                                               return 
indexOp("getKey", indexName, [key]);
+                                                       }
+                                               };
+                                       };
+
+                                       return result;
+                               }
+                       });
+               }
+       });
+
+       $.indexedDB.IDBCursor = IDBCursor;
+       $.indexedDB.IDBTransaction = IDBTransaction;
+       $.idb = $.indexedDB;
+})(jQuery);

-- 
To view, visit https://gerrit.wikimedia.org/r/157818
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I9b5ccc018ad19ae3abcc95e879e9c4a467533d71
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: TheDJ <hartman.w...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to