--- /dev/null
+/*
+ * couchdb.js - couchdb interface
+ *
+ * author: hackbard@hackdaworld.org
+ *
+ */
+
+var couchdb = {
+ type: "http",
+ host: "cdbsrv",
+ port: "80",
+ prefix: "",
+ init: function(type,host,port,prefix) {
+ if(type!==undefined)
+ couchdb.type=type;
+ if(host!==undefined)
+ couchdb.host=host;
+ if(port!==undefined)
+ couchdb.port=port;
+ if(prefix!==undefined)
+ couchdb.prefix=prefix;
+ },
+ cdb_xhr: function(type,url,data,cb) {
+ var ao={
+ url: url,
+ type: type,
+ success: function(ret) {
+ var ro=JSON.parse(ret);
+ if('error' in ro) {
+ switch(ro.error) {
+ case "file_exists":
+ cl("couchdb: exists - "+
+ url);
+ break;
+ case "not_found":
+ cl("couchdb: not found"+
+ " - "+url);
+ break;
+ default:
+ cl("couchdb: error - "+
+ url);
+ cl(ret);
+ }
+ }
+ else {
+ cl("couchdb: xhr success - "+url);
+ }
+ if(cb!==undefined)
+ cb(ro);
+ },
+ error: function(xhr,stat,err) {
+ cl("conn: "+url+", error: "+err+
+ ", stat: "+stat);
+ cl("executing callback anyways ...");
+ cb();
+ }
+ };
+ if((data!==undefined)&&(data!==null))
+ ao.data=JSON.stringify(data);
+ $.ajax(ao);
+ },
+ item_count: function(db,callback) {
+ var url=couchdb.type+"://"+couchdb.host+":"+couchdb.port+"/"+
+ couchdb.prefix+db+"/_all_docs?limit=0";
+ couchdb.cdb_xhr('GET',url,null,function(ret) {
+ callback(ret.total_rows);
+ });
+ },
+ get_item: function(db,key,callback) {
+ var url=couchdb.type+"://"+couchdb.host+":"+couchdb.port+"/"+
+ couchdb.prefix+db+"/"+key;
+ couchdb.cdb_xhr('GET',url,null,function(ret) {
+ callback(ret);
+ });
+ },
+ get_db: function(db,callback) {
+ var url=couchdb.type+"://"+couchdb.host+":"+couchdb.port+"/"+
+ couchdb.prefix+db+"/_all_docs?include_docs=true";
+ couchdb.cdb_xhr('GET',url,null,function(ret) {
+ callback(ret);
+ });
+ },
+ add_item: function(db,key,data,callback) {
+ var url=couchdb.type+"://"+couchdb.host+":"+couchdb.port+"/"+
+ couchdb.prefix+db+"/"+k;
+ couchdb.cdb_xhr('PUT',url,data,function(ret) {
+ callback(ret);
+ });
+ }
+};
--- /dev/null
+/*
+ * idb.js - indexed db interface
+ *
+ * author: hackbard@hackdaworld.org
+ *
+ */
+
+var idb = {
+ version: '1',
+ name: 'idb',
+ handle: null,
+ stores: {},
+ onupgradeneeded: function(event) {
+ idb.handle=event.target.result;
+ idb.handle.onerror=function(event) {
+ cl("idb: handle error - "+event.target.errorCode);
+ };
+ var ov=event.oldVersion;
+ var nv=event.newVersion;
+ if(ov<idb.version) {
+ cl("idb: version upgrade ("+ov+" -> "+nv+')!');
+ // stores
+ for(var sn in idb.stores) {
+ // key
+ var store=idb.stores[sn]
+ var key={};
+ key[store['keytype']]=store['keyname'];
+ cl("idb: creating store '"+sn+"'");
+ store.os=idb.handle.createObjectStore(sn,key);
+ // indices
+ if(store.idx!==undefined) {
+ var idx=store.idx[nv];
+ if(idx===undefined) {
+ cl('idb: missing version '+nv);
+ }
+ for(var iname in idx) {
+ cl("idb: creating index '"+
+ iname+"' u: "+
+ idx[iname].unique+
+ " in store "+sn);
+ store.os.createIndex(iname,
+ iname,
+ idx[iname]);
+ }
+ }
+ // content
+ vc=null;
+ if(store.content!==undefined) {
+ vc=store.content[nv];
+ }
+ if(vc===null) continue;
+ if(vc!==undefined) {
+ cl("idb: put content to store '"+
+ sn+"'");
+ for(var c in vc) {
+ objdbg(vc[c]);
+ store.os.put(vc[c]);
+ }
+ }
+ }
+ }
+ cl("idb: upgrade success! ("+ov+"->"+nv+")");
+ },
+ onsuccess: function(event) {
+ idb.handle=event.target.result;
+ cl("idb: initialized successfuly ...");
+ idb.successcb(event);
+ },
+ onerror: function(event) {
+ cl("idb: error - "+this.error.message);
+ },
+ onblocked: function(event) {
+ cl("idb: blocked");
+ },
+ init: function(name,successcb,version,stores,upgradecb) {
+ if(!indexedDB) {
+ cl("idb: indexed db not supported");
+ return
+ }
+ if(name!==undefined)
+ idb.name=name;
+ if(version!==undefined)
+ idb.version=version;
+ if(stores!==undefined)
+ idb.stores=stores;
+ if(successcb!==undefined)
+ idb.successcb=successcb;
+ if(upgradecb!==undefined)
+ idb.onupgradeneeded=upgradecb;
+ var req=indexedDB.open(idb.name,idb.version);
+ req.onsuccess=idb.onsuccess;
+ req.onupgradeneeded=idb.onupgradeneeded;
+ req.onerror=idb.onerror;
+ req.onblocked=idb.onblocked;
+ },
+ add_store_item: function(store,item,callback) {
+ var tx=idb.handle.transaction(store,'readwrite');
+ var store=tx.objectStore(store);
+ var req=store.add(item);
+ req.onsuccess=function(event) {
+ callback(event);
+ };
+ req.onerror=function(error) {
+ cl("idb: add item error, "+error);
+ };
+ },
+ del_store: function(store,callback) {
+ var tx=db.handle.transaction(store,'readwrite');
+ var store=tx.objectStore(store);
+ var req=store.clear();
+ req.onsuccess=function() {
+ cl("db: store "+store.name+" deleted");
+ callback();
+ };
+ },
+ del_store_item: function(store,num,callback) {
+ var tx=db.handle.transaction(store,'readwrite');
+ var store=tx.objectStore(store);
+
+ var kr=IDBKeyRange.bound(num,num,false,false);
+ var req=store.openCursor(kr);
+
+ req.onsuccess=function(event) {
+ var cursor=event.target.result;
+ if(cursor) {
+ var res=cursor.delete();
+ res.onsuccess=function(event) {
+ callback(event);
+ };
+ res.onerror=function(error) {
+ cl("db: delete error");
+ };
+ return;
+ //cursor.continue();
+ }
+ else {
+ cl("db: nothing to delete");
+ }
+
+ };
+ },
+ update_store_item: function(store,num,nitem,callback) {
+ var tx=idb.handle.transaction(store,'readwrite');
+ var store=tx.objectStore(store);
+
+ var kr=IDBKeyRange.bound(num,num,false,false);
+ var req=store.openCursor(kr);
+
+ req.onsuccess=function(event) {
+ var cursor=event.target.result;
+ if(cursor) {
+ var oitem=cursor.value;
+ var notreq=true;
+ for(var k in oitem) {
+ if(JSON.stringify(oitem[k])!=
+ JSON.stringify(nitem[k])) {
+ oitem[k]=nitem[k];
+ cl("idb: modified "+k);
+ notreq=false;
+ }
+ }
+ if(notreq) {
+ return;
+ }
+ var res=cursor.update(nitem);
+ res.onsuccess=function(event) {
+ cl("idb: updated cursor");
+ callback(event);
+ };
+ res.onerror=function(error) {
+ cl("idb: cursor update error");
+ };
+ return;
+ //cursor.continue();
+ }
+ else {
+ var addreq=store.add(nitem,num);
+ addreq.onsuccess=function(event) {
+ cl("idb: added (update mode) key "+num);
+ callback(event);
+ }
+ addreq.onerror=function(error) {
+ cl("idb: error add (update mode)");
+ };
+ }
+
+ };
+ },
+ get_store_items: function(store,callback,low,up) {
+ // if low and up are undefined, all items are considered
+ var kr;
+ var last=false;
+ var reversed=false;
+ if((low!==undefined)&&(up!==undefined)) {
+ if((low===0)&&(up<0)) {
+ // get last up items
+ last=true;
+ }
+ else if((low===0)&&(up===0)) {
+ // get all items in reversed order
+ // no key range, no stop criteria required!
+ reversed=true;
+ }
+ else {
+ // get items in range
+ kr=IDBKeyRange.bound(low,up,true,true);
+ }
+ }
+ else if (low!==undefined) {
+ // get items from low to current
+ kr=IDBKeyRange.lowerBound(low,true);
+ }
+ else if (up!==undefined) {
+ // get items from first to up
+ kr=IDBKeyRange.upperBound(up,true);
+ }
+
+ var tx=idb.handle.transaction(store,'readonly');
+ var store=tx.objectStore(store);
+
+ var obj={};
+ obj.cnt_objs=0;
+
+ if(last||reversed) {
+ var req=store.openCursor(null,"prev");
+ }
+ else {
+ if(kr!==undefined)
+ var req=store.openCursor(kr);
+ else
+ // get all items
+ var req=store.openCursor();
+ }
+
+ req.onerror=function(error) {
+ cl("idb: cursor error - "+error);
+ };
+ req.onsuccess=function(event) {
+ var cursor=event.target.result;
+ if(cursor&&(!(last&&(obj.cnt_objs==-up)))) {
+ obj[cursor.key]=cursor.value;
+ obj.cnt_objs+=1;
+ cursor.continue();
+ } else {
+ delete obj.cnt_objs;
+ callback(obj);
+ }
+ };
+ },
+ get_item_by_key: function(store,key,callback) {
+ var tx=idb.handle.transaction(store,'readonly')
+ var store=tx.objectStore(store);
+ var req=store.get(key);
+ req.onerror=function(event) {
+ cl("idb: get key error - "+event.target.errorCode);
+ }
+ req.onsuccess=function(event) {
+ if(event.target.result!=null) {
+ callback(event.target.result);
+ }
+ }
+ },
+ get_item_by_index: function(store,index,val,callback) {
+ var tx=db.handle.transaction(store,'readonly')
+ var store=tx.objectStore(store);
+ var idx=store.index(index);
+ var req=idx.get(val);
+ req.onerror=function(event) {
+ cl("db: error! "+event.target.errorCode);
+ }
+ req.onsuccess=function(event) {
+ if(event.target.result!=null) {
+ callback(event.target.result);
+ }
+ }
+ },
+ del_item_by_key: function(store,key,callback) {
+ var tx=idb.handle.transaction(store,'readwrite');
+ var store=tx.objectStore(store);
+
+ var kr=IDBKeyRange.bound(key,key,false,false);
+ var req=store.openCursor(kr);
+
+ req.onsuccess=function(event) {
+ var cursor=event.target.result;
+ if(cursor) {
+ var res=cursor.delete();
+ res.onsuccess=function(event) {
+ cl("idb: deleted key "+key);
+ callback(event);
+ };
+ res.onerror=function(error) {
+ cl("idb: cursor delete error");
+ };
+ }
+ else {
+ cl('idb: nothing to delete');
+ }
+
+ };
+ },
+ del: function() {
+ var req=indexedDB.deleteDatabase(idb.name);
+ req.onsuccess=function() {
+ cl("idb: deleted database '"+idb.name+"'");
+ };
+ req.onblocked=function() {
+ cl("idb: database delete blocked");
+ };
+ req.onerror=function() {
+ cl("idb: delete database error");
+ };
+ }
+};
+