code style updates

This commit is contained in:
Stewart Allen 2022-01-31 21:19:21 -05:00
commit 7c6a34c743
5 changed files with 670 additions and 688 deletions

View file

@ -2,258 +2,236 @@
"use strict";
// extend Array, String, Number, Math
(function() {
gapp.register('add.array');
gapp.register('add.array');
let AP = {};
let AP = {};
/** ******************************************************************
* Array prototype helpers
******************************************************************* */
if (!AP.flat) {
AP.flat = function() {
return [].concat.apply([], this);
};
}
if (!AP.flat) {
AP.flat = function() {
return [].concat.apply([], this);
};
}
AP.equals = function(arr) {
if (!arr) return false;
if (arr.length !== this.length) return false;
for (let i = 0; i < this.length; i++) {
if (arr[i] !== this[i]) return false;
}
return true;
};
AP.equals = function(arr) {
if (!arr) return false;
if (arr.length !== this.length) return false;
for (let i=0; i<this.length; i++) {
if (arr[i] !== this[i]) return false;
}
return true;
};
AP.peek = function() {
return this[this.length - 1];
};
AP.peek = function() {
return this[this.length-1];
};
/**
* allow chaining of push() calls
*/
AP.append = function(v, flat) {
if (flat) {
return this.appendAll(v);
} else {
this.push(v);
return this;
}
};
/**
* allow chaining of push() calls
*
* @param v
* @returns {Array}
*/
AP.append = function(v, flat) {
if (flat) {
return this.appendAll(v);
/**
* append all array elements to this array
*/
AP.appendAll = function(arr) {
if (arr && arr.length > 0) {
// avoid hitting stack limits
if (arr.length > 10000) {
for (let i = 0, il = arr.length; i < il; i++) {
this.push(arr[i]);
}
} else {
this.push(v);
return this;
// this.push.apply(this,arr); (slower?)
this.push(...arr);
}
};
}
return this;
};
/**
* append all array elements to this array
*
* @param {Array} arr
* @returns {Array}
*/
AP.appendAll = function(arr) {
if (arr && arr.length > 0) {
// avoid hitting stack limits
if (arr.length > 10000) {
for (let i=0, il=arr.length; i<il; i++) {
this.push(arr[i]);
AP.addOnce = function(val) {
if (!this.contains(val)) {
this.push(val);
}
return this;
};
/**
* shallow cloning with clone(arg) call on each new element
*/
AP.clone = function(arg) {
var na = this.slice(),
ln = na.length,
i = 0;
while (i < ln) na[i] = na[i++].clone(arg);
return na;
};
AP.xray = function(arg) {
const na = [],
ln = this.length;
for (let i = 0; i < ln; i++) {
na.push(this[i].xray(arg));
}
return na;
};
AP.xout = function(label, inset) {
if (label) console.log(`${label} [${this.length}]`);
if (!inset) inset = ' ';
this.forEach((el, i) => {
if (el.xout) {
el.xout(null, inset + i + inset);
} else if (el.xray) {
const info = el.xray();
console.log(inset, info);
Object.values(info).forEach(val => {
if (val.xout) {
val.xout(null, inset + inset);
}
} else {
// this.push.apply(this,arr); (slower?)
this.push(...arr);
});
}
});
};
/**
* remove and return element from array, if present
*/
AP.remove = function(val) {
var idx = this.indexOf(val);
if (idx >= 0) return this.splice(idx, 1);
return null;
};
AP.removeAll = function(array) {
for (let i = 0, il = array.length; i < il; i++) {
this.remove(array[i]);
}
};
/**
* return last array element if array length > 0
*/
AP.last = function() {
if (this.length === 0) return null;
return this[this.length - 1];
};
AP.contains = function(val) {
return this.indexOf(val) >= 0;
};
AP.toFloat32 = function() {
var i = 0,
f32 = new Float32Array(this.length);
while (i < this.length) {
f32[i] = this[i++];
}
return f32;
};
AP.forEachPair = function(fn, incr) {
var scope = this,
idx = 0,
inc = incr || 2,
len = scope.length;
while (idx < len) {
fn(scope[idx], scope[(idx + 1) % len], idx);
idx += inc;
}
};
AP.show = function(fn, f) {
f = f || function(v) {
console.log(v)
};
this.forEach(function(av) {
f(av[fn]());
})
};
AP.uniq = function() {
return this.slice().sort().filter((x, i, a) => !i || x != a[i - 1]);
};
AP.hasNaN = function() {
return this.filter(v => isNaN(v)).length > 0;
};
// turn array into arrays of specified size
AP.group = function(size) {
let na = new Array(Math.ceil(this.length / size));
let nai = 0;
for (let i = 0; i < this.length; i += size) {
let grp = new Array(size);
for (let j = 0; j < size; j++) {
grp[j] = this[i + j];
}
na[nai++] = grp;
}
return na;
};
// wrap a function and unroll the first parameter into
// successive function calls if it is an array
Array.handle = function(fn) {
return function() {
let args = [...arguments];
let val = args.shift();
if (Array.isArray(val)) {
let rv = [];
for (let v of val.slice()) {
rv.push(fn(v, ...args));
}
return rv;
} else {
return fn(val, ...args);
}
return this;
};
}
};
AP.addOnce = function(val) {
if (!this.contains(val)) {
this.push(val);
}
return this;
};
for (let i in AP) {
Object.defineProperty(Array.prototype, i, {
value: AP[i],
enumerable: false
});
}
/**
* shallow cloning with clone(arg) call on each new element
*
* @param {Array} [arg]
* @returns {Array}
*/
AP.clone = function(arg) {
var na = this.slice(),
ln = na.length,
i = 0;
while (i < ln) na[i] = na[i++].clone(arg);
return na;
};
String.prototype.reverse = function() {
return this.split('').reverse().join('');
};
AP.xray = function(arg) {
const na = [], ln = this.length;
for (let i=0; i<ln; i++) {
na.push(this[i].xray(arg));
}
return na;
};
Object.clone = function(o) {
return o ? JSON.parse(JSON.stringify(o)) : o;
};
AP.xout = function(label, inset) {
if (label) console.log(`${label} [${this.length}]`);
if (!inset) inset = ' ';
this.forEach((el,i) => {
if (el.xout) {
el.xout(null, inset + i + inset);
} else if (el.xray) {
const info = el.xray();
console.log(inset, info);
Object.values(info).forEach(val => {
if (val.xout) {
val.xout(null, inset + inset);
}
});
}
});
};
/**
* remove and return element from array, if present
*
* @param val
* @returns {*}
*/
AP.remove = function(val) {
var idx = this.indexOf(val);
if (idx >= 0) return this.splice(idx,1);
return null;
};
AP.removeAll = function(array) {
for (let i=0, il=array.length; i<il; i++) {
this.remove(array[i]);
}
};
/**
* return last array element if array length > 0
*
* @returns {*}
*/
AP.last = function() {
if (this.length === 0) return null;
return this[this.length-1];
};
AP.contains = function(val) {
return this.indexOf(val) >= 0;
};
AP.toFloat32 = function() {
var i = 0, f32 = new Float32Array(this.length);
while (i < this.length) {
f32[i] = this[i++];
}
return f32;
};
AP.forEachPair = function(fn, incr) {
var scope = this,
idx = 0,
inc = incr || 2,
len = scope.length;
while (idx < len) {
fn(scope[idx], scope[(idx+1)%len], idx);
idx += inc;
}
};
AP.show = function(fn,f) {
f = f || function(v) { console.log(v) };
this.forEach(function(av) {
f(av[fn]());
})
};
AP.uniq = function() {
return this.slice().sort().filter((x, i, a) => !i || x != a[i-1]);
};
AP.hasNaN = function() {
return this.filter(v => isNaN(v)).length > 0;
};
// turn array into arrays of specified size
AP.group = function(size) {
let na = new Array(Math.ceil(this.length / size));
let nai = 0;
for (let i=0; i<this.length; i += size) {
let grp = new Array(size);
for (let j=0; j<size; j++) {
grp[j] = this[i+j];
}
na[nai++] = grp;
}
return na;
};
// wrap a function and unroll the first parameter into
// successive function calls if it is an array
Array.handle = function(fn) {
return function() {
let args = [...arguments];
let val = args.shift();
if (Array.isArray(val)) {
let rv = [];
for (let v of val.slice()) {
rv.push(fn(v, ...args));
}
return rv;
} else {
return fn(val, ...args);
}
}
};
for (let i in AP) {
Object.defineProperty(Array.prototype, i, {
value: AP[i],
enumerable: false
Object.toArray = function(o) {
let ret = [];
for (let [key, value] of Object.entries(o)) {
ret.push({
key,
value
});
}
return ret;
};
/** ******************************************************************
* String prototype helpers
******************************************************************* */
Math.bound = function(val, min, max) {
return Math.max(min, Math.min(max, val));
};
String.prototype.reverse = function() {
return this.split('').reverse().join('');
};
/** ******************************************************************
* Object static helpers
******************************************************************* */
Object.clone = function(o) {
return o ? JSON.parse(JSON.stringify(o)) : o;
};
Object.toArray = function(o) {
let ret = [];
for (let [key,value] of Object.entries(o)) {
ret.push({key, value});
}
return ret;
};
Math.bound = function(val,min,max) {
return Math.max(min,Math.min(max,val));
};
/** ******************************************************************
* Number static helpers
******************************************************************* */
Number.prototype.round = function(digits) {
const pow = Math.pow(10,digits || 3);
return Math.round(this.valueOf() * pow) / pow;
};
Number.prototype.round = function(digits) {
const pow = Math.pow(10, digits || 3);
return Math.round(this.valueOf() * pow) / pow;
};
})();

View file

@ -2,9 +2,11 @@
"use strict";
if (!self.ArrayWriter) {
gapp.register('add.class');
}
(function() {
if (self.ArrayWriter) return;
gapp.register('add.class');
self.ArrayWriter = class ArrayWriter {
constructor() {
@ -171,3 +173,5 @@ self.DataReader = class DataReader {
return v;
}
}
})();

View file

@ -4,129 +4,129 @@
(function() {
// dep: ext.three
// dep: ext.three-bgu
// dep: ext.three-svg
gapp.register('add.three');
// dep: ext.three
// dep: ext.three-bgu
// dep: ext.three-svg
gapp.register('add.three');
let MP = THREE.Mesh.prototype,
XP = THREE.Box3.prototype,
BP = THREE.BufferGeometry.prototype;
let MP = THREE.Mesh.prototype,
XP = THREE.Box3.prototype,
BP = THREE.BufferGeometry.prototype;
THREE.computeFaceNormal = function(vA,vB,vC) {
const ab = new THREE.Vector3();
const cb = new THREE.Vector3();
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
cb.normalize();
return cb;
};
THREE.computeFaceNormal = function(vA,vB,vC) {
const ab = new THREE.Vector3();
const cb = new THREE.Vector3();
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
cb.normalize();
return cb;
};
THREE.dispose = function(obj) {
if (!obj) {
return;
}
if (obj.geometry) {
obj.geometry.dispose();
}
if (obj.material && obj.material.map && obj.material.map.dispose) {
obj.material.map.dispose();
}
if (obj.children && obj.children.length) {
for (let c of obj.children) {
THREE.dispose(c);
}
}
};
// add .dim and .mid getters to Box3
Object.defineProperties(XP, {
dim: {
get: function() {
return this.max.clone().sub(this.min);
}
},
mid: {
get: function() {
return this.dim.clone().multiplyScalar(0.5).add(this.min);
}
}
});
MP.getBoundingBox = function(update) {
return this.geometry.getBoundingBox(update);
};
MP.mirrorX = function() {
return this.mirror(0);
};
MP.mirrorY = function() {
return this.mirror(1);
};
MP.mirrorZ = function() {
return this.mirror(2);
};
// fast mirror of vertices given axis array offset
// array elements are repeating [x,y,z,x,y,z,...]
MP.mirror = function(start) {
let i,
geo = this.geometry,
at = geo.attributes,
pa = at.position.array,
nm = at.normal.array;
for (i = start || 0 ; i < pa.length; i += 3) {
pa[i] = -pa[i];
nm[i] = -nm[i];
}
geo.computeVertexNormals();
return this;
};
// return cached or refreshed (when update = true) bounding box
BP.getBoundingBox = function(update) {
if (update || !this.boundingBox) {
this.boundingBox = null;
this.computeBoundingBox();
}
return this.boundingBox;
};
BP.moveMesh = function(x = 0, y = 0, z = 0) {
let gap = this.attributes.position,
pa = gap.array;
for (let i=0; i < pa.length; i += 3) {
pa[i ] += x;
pa[i + 1] += y;
pa[i + 2] += z;
}
gap.needsUpdate = true;
return this;
THREE.dispose = function(obj) {
if (!obj) {
return;
}
BP.shallowClone = function() {
let geo = new THREE.BufferGeometry();
for (let [k, v] of Object.entries(this.attributes)) {
geo.setAttribute(k, new THREE.BufferAttribute(v.array, v.itemSize));
if (obj.geometry) {
obj.geometry.dispose();
}
if (obj.material && obj.material.map && obj.material.map.dispose) {
obj.material.map.dispose();
}
if (obj.children && obj.children.length) {
for (let c of obj.children) {
THREE.dispose(c);
}
return geo;
};
}
};
THREE.Object3D.prototype.newGroup = function() {
let group = new THREE.Group();
this.add(group);
return group;
};
// add .dim and .mid getters to Box3
Object.defineProperties(XP, {
dim: {
get: function() {
return this.max.clone().sub(this.min);
}
},
mid: {
get: function() {
return this.dim.clone().multiplyScalar(0.5).add(this.min);
}
}
});
THREE.Object3D.prototype.removeAll = function() {
this.children.slice().forEach(function (c) {
c.parent = undefined;
c.dispatchEvent( { type: 'removed' } );
});
this.children = [];
};
MP.getBoundingBox = function(update) {
return this.geometry.getBoundingBox(update);
};
MP.mirrorX = function() {
return this.mirror(0);
};
MP.mirrorY = function() {
return this.mirror(1);
};
MP.mirrorZ = function() {
return this.mirror(2);
};
// fast mirror of vertices given axis array offset
// array elements are repeating [x,y,z,x,y,z,...]
MP.mirror = function(start) {
let i,
geo = this.geometry,
at = geo.attributes,
pa = at.position.array,
nm = at.normal.array;
for (i = start || 0 ; i < pa.length; i += 3) {
pa[i] = -pa[i];
nm[i] = -nm[i];
}
geo.computeVertexNormals();
return this;
};
// return cached or refreshed (when update = true) bounding box
BP.getBoundingBox = function(update) {
if (update || !this.boundingBox) {
this.boundingBox = null;
this.computeBoundingBox();
}
return this.boundingBox;
};
BP.moveMesh = function(x = 0, y = 0, z = 0) {
let gap = this.attributes.position,
pa = gap.array;
for (let i=0; i < pa.length; i += 3) {
pa[i ] += x;
pa[i + 1] += y;
pa[i + 2] += z;
}
gap.needsUpdate = true;
return this;
}
BP.shallowClone = function() {
let geo = new THREE.BufferGeometry();
for (let [k, v] of Object.entries(this.attributes)) {
geo.setAttribute(k, new THREE.BufferAttribute(v.array, v.itemSize));
}
return geo;
};
THREE.Object3D.prototype.newGroup = function() {
let group = new THREE.Group();
this.add(group);
return group;
};
THREE.Object3D.prototype.removeAll = function() {
this.children.slice().forEach(function (c) {
c.parent = undefined;
c.dispatchEvent( { type: 'removed' } );
});
this.children = [];
};
})();

View file

@ -4,322 +4,322 @@
(function() {
gapp.register('data.index');
gapp.register('data.index');
let data = self.data = self.data || {};
if (data.Index) return;
let data = self.data = self.data || {};
if (data.Index) return;
data.Index = IDBStore;
data.Index = IDBStore;
data.open = function() {
return new IDBStore(...arguments);
data.open = function() {
return new IDBStore(...arguments);
};
// https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
let IDB, IRR, local = null;
try {
IDB = self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB;
IRR = self.IDBKeyRange;
} catch (e) {
console.log("in private or restricted browsing mode. database storage blocked. application may not function.");
}
/**
* @param {String} dbname
* @param {number} [version]
* @constructor
*/
function IDBStore(dbname, options = {}) {
this.db = null;
this.name = dbname;
this.stores = options.stores || [ dbname ];
this.version = options.version || 1;
this.queue = [];
this.idle = [];
this.initCalled = false;
this.created = {};
}
IDBStore.delete = function(dbname) {
IDB.deleteDatabase(dbname);
};
let SP = IDBStore.prototype;
/** ******************************************************************
* indexedDB implementation
******************************************************************* */
SP.onIdle = function(fn) {
if (this.queue.length) {
this.idle.push(fn);
} else {
fn();
}
return this;
};
SP.promise = function(store) {
let db = this;
let pc = {
iterate: (opt = {}) => new Promise(function(resolve, reject) {
let { lower, upper, collect } = opt;
if (!collect) {
let rval = opt.map ? {} : [];
collect = (key, value) => {
if (key !== null) {
if (opt.map) {
rval[key] = value;
} else {
rval.push({key, value});
}
} else {
resolve(rval);
}
};
} else {
resolve();
}
db.iterate(collect, lower, upper, true, store);
}),
get: (key) => new Promise(function(resolve, reject) {
db.get(key, resolve, store);
}),
put: (key, value) => new Promise(function(resolve, reject) {
db.put(key, value, resolve, store);
}),
remove: (key) => new Promise(function(resolve, reject) {
db.remove(key, resolve, store);
}),
// wait for all outstanding transactions to complete
wait: () => new Promise(function(resolve, reject) {
db.onIdle(promise);
}),
use: (store) => {
db.use(store);
return pc;
},
};
return pc;
}
// https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
SP.keys = function(callback, lower, upper, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(["keys", callback, lower, upper, store]);
}
let out = [];
this.iterate(function(k,v) {
if (k === null) {
callback(out);
} else {
out.push(k);
}
}, lower, upper, true, store);
};
let IDB, IRR, local = null;
SP.iterate = function(callback, lower, upper, nullterm, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(["iterate", callback, lower, upper, nullterm, store]);
}
let range = lower && upper ? IRR.bound(lower,upper) :
lower ? IRR.lowerBound(lower) :
upper ? IRR.upperBound(upper) : undefined;
// iterate over all db values for debugging
this.db
.transaction(store)
.objectStore(store)
.openCursor(range).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
callback(cursor.key, cursor.value);
cursor.continue();
} else if (nullterm) {
callback(null);
}
};
};
SP.deleteStore = function() {
if (this.initCalled) throw "cannot delete ObjectStore after init() called";
this.version = Number.MAX_SAFE_INTEGER || Number.MAX_VALUE;
return this.init(true);
};
SP.use = function(store) {
this.current = store;
return this;
}
SP.init = function(options = {}) {
if (this.initCalled) return;
let storage = this,
name = this.name,
request = null;
function fallback() {
console.log("in private browsing mode or browser lacks support for IndexedDB. unable to setup storage for '" + name + "'.");
local = {};
storage.runQueue();
}
try {
IDB = self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB;
IRR = self.IDBKeyRange;
} catch (e) {
console.log("in private or restricted browsing mode. database storage blocked. application may not function.");
}
request = IDB.open(name, this.version);
/**
* @param {String} dbname
* @param {number} [version]
* @constructor
*/
function IDBStore(dbname, options = {}) {
this.db = null;
this.name = dbname;
this.stores = options.stores || [ dbname ];
this.version = options.version || 1;
this.queue = [];
this.idle = [];
this.initCalled = false;
this.created = {};
}
IDBStore.delete = function(dbname) {
IDB.deleteDatabase(dbname);
};
let SP = IDBStore.prototype;
/** ******************************************************************
* indexedDB implementation
******************************************************************* */
SP.onIdle = function(fn) {
if (this.queue.length) {
this.idle.push(fn);
} else {
fn();
}
return this;
};
SP.promise = function(store) {
let db = this;
let pc = {
iterate: (opt = {}) => new Promise(function(resolve, reject) {
let { lower, upper, collect } = opt;
if (!collect) {
let rval = opt.map ? {} : [];
collect = (key, value) => {
if (key !== null) {
if (opt.map) {
rval[key] = value;
} else {
rval.push({key, value});
}
} else {
resolve(rval);
}
};
} else {
resolve();
request.onupgradeneeded = function(event) {
let db = storage.db = request.result;
let current = [...db.objectStoreNames];
let stores = storage.stores;
// add missing stores
for (let store of stores) {
if (current.indexOf(store) >= 0) {
continue;
}
db.iterate(collect, lower, upper, true, store);
}),
get: (key) => new Promise(function(resolve, reject) {
db.get(key, resolve, store);
}),
put: (key, value) => new Promise(function(resolve, reject) {
db.put(key, value, resolve, store);
}),
remove: (key) => new Promise(function(resolve, reject) {
db.remove(key, resolve, store);
}),
// wait for all outstanding transactions to complete
wait: () => new Promise(function(resolve, reject) {
db.onIdle(promise);
}),
use: (store) => {
db.use(store);
return pc;
},
};
return pc;
}
SP.keys = function(callback, lower, upper, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(["keys", callback, lower, upper, store]);
}
let out = [];
this.iterate(function(k,v) {
if (k === null) {
callback(out);
} else {
out.push(k);
storage.created[store] = db.createObjectStore(store);
storage.current = store;
current.push(store);
console.log({index_added: store});
}
}, lower, upper, true, store);
};
SP.iterate = function(callback, lower, upper, nullterm, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(["iterate", callback, lower, upper, nullterm, store]);
}
let range = lower && upper ? IRR.bound(lower,upper) :
lower ? IRR.lowerBound(lower) :
upper ? IRR.upperBound(upper) : undefined;
// iterate over all db values for debugging
this.db
.transaction(store)
.objectStore(store)
.openCursor(range).onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
callback(cursor.key, cursor.value);
cursor.continue();
} else if (nullterm) {
callback(null);
// remove obsolete stores
for (let curr of current) {
if (stores.indexOf(curr) < 0) {
storage.db.deleteObjectStore(curr);
console.log({index_dropped: curr});
}
};
};
SP.deleteStore = function() {
if (this.initCalled) throw "cannot delete ObjectStore after init() called";
this.version = Number.MAX_SAFE_INTEGER || Number.MAX_VALUE;
return this.init(true);
};
SP.use = function(store) {
this.current = store;
return this;
}
SP.init = function(options = {}) {
if (this.initCalled) return;
let storage = this,
name = this.name,
request = null;
function fallback() {
console.log("in private browsing mode or browser lacks support for IndexedDB. unable to setup storage for '" + name + "'.");
local = {};
storage.runQueue();
}
try {
request = IDB.open(name, this.version);
request.onupgradeneeded = function(event) {
let db = storage.db = request.result;
let current = [...db.objectStoreNames];
let stores = storage.stores;
// add missing stores
for (let store of stores) {
if (current.indexOf(store) >= 0) {
continue;
}
storage.created[store] = db.createObjectStore(store);
storage.current = store;
current.push(store);
console.log({index_added: store});
}
// remove obsolete stores
for (let curr of current) {
if (stores.indexOf(curr) < 0) {
storage.db.deleteObjectStore(curr);
console.log({index_dropped: curr});
}
}
event.target.transaction.oncomplete = function(event) {
storage.runQueue();
};
};
request.onsuccess = function(event) {
storage.current = storage.stores[0];
storage.db = request.result;
}
event.target.transaction.oncomplete = function(event) {
storage.runQueue();
};
};
request.onerror = function(event) {
console.log({error: event});
fallback();
};
} catch (e) {
request.onsuccess = function(event) {
storage.current = storage.stores[0];
storage.db = request.result;
storage.runQueue();
};
request.onerror = function(event) {
console.log({error: event});
fallback();
return;
}
};
} catch (e) {
fallback();
return;
}
this.initCalled = true;
return this;
};
this.initCalled = true;
return this;
};
SP.runQueue = function() {
if (this.queue.length > 0) {
let i = 0, q = this.queue, e;
while (i < q.length) {
e = q[i++];
switch (e.shift()) {
case 'iterate': this.iterate(...e); break;
case 'keys': this.keys(...e); break;
case 'put': this.put(...e); break;
case 'get': this.get(...e); break;
case 'remove': this.remove(...e); break;
case 'clear': this.clear(...e);
}
SP.runQueue = function() {
if (this.queue.length > 0) {
let i = 0, q = this.queue, e;
while (i < q.length) {
e = q[i++];
switch (e.shift()) {
case 'iterate': this.iterate(...e); break;
case 'keys': this.keys(...e); break;
case 'put': this.put(...e); break;
case 'get': this.get(...e); break;
case 'remove': this.remove(...e); break;
case 'clear': this.clear(...e);
}
this.queue = [];
}
while (this.idle.length) {
this.idle.shift()();
}
};
this.queue = [];
}
while (this.idle.length) {
this.idle.shift()();
}
};
SP.put = function(key, value, callback, store = this.current) {
if (local) {
local[key] = value;
if (callback) callback(true);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['put', key, value, callback, store]);
}
try {
let req = this.db
.transaction(store, "readwrite")
.objectStore(store).put(value, key);
if (callback) {
req.onsuccess = function(event) { callback(true) };
req.onerror = function(event) { callback(false) };
}
} catch (e) {
console.log(e);
if (callback) callback(false);
}
};
SP.get = function(key, callback, store = this.current) {
if (local) {
if (callback) callback(local[key]);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['get', key, callback, store]);
}
try {
let req = this.db
.transaction(store)
.objectStore(store).get(key);
if (callback) {
req.onsuccess = function(event) { callback(req.result) };
req.onerror = function(event) { callback(null) };
}
} catch (e) {
console.log(e);
if (callback) callback(null);
}
};
SP.remove = function(key, callback, store = this.current) {
if (local) {
delete local[key];
if (callback) callback(true);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['remove', key, callback, store]);
}
try {
let req = this.db
.transaction(store, "readwrite")
.objectStore(store).delete(key);
if (callback) {
req.onsuccess = function(event) { callback(true) };
req.onerror = function(event) { callback(false) };
}
} catch (e) {
console.log(e);
if (callback) callback(false);
}
};
SP.clear = function(key, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(['clear', store]);
}
this.db
SP.put = function(key, value, callback, store = this.current) {
if (local) {
local[key] = value;
if (callback) callback(true);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['put', key, value, callback, store]);
}
try {
let req = this.db
.transaction(store, "readwrite")
.objectStore(store).clear();
};
.objectStore(store).put(value, key);
if (callback) {
req.onsuccess = function(event) { callback(true) };
req.onerror = function(event) { callback(false) };
}
} catch (e) {
console.log(e);
if (callback) callback(false);
}
};
SP.get = function(key, callback, store = this.current) {
if (local) {
if (callback) callback(local[key]);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['get', key, callback, store]);
}
try {
let req = this.db
.transaction(store)
.objectStore(store).get(key);
if (callback) {
req.onsuccess = function(event) { callback(req.result) };
req.onerror = function(event) { callback(null) };
}
} catch (e) {
console.log(e);
if (callback) callback(null);
}
};
SP.remove = function(key, callback, store = this.current) {
if (local) {
delete local[key];
if (callback) callback(true);
return;
}
if (!this.db) {
this.init();
return this.queue.push(['remove', key, callback, store]);
}
try {
let req = this.db
.transaction(store, "readwrite")
.objectStore(store).delete(key);
if (callback) {
req.onsuccess = function(event) { callback(true) };
req.onerror = function(event) { callback(false) };
}
} catch (e) {
console.log(e);
if (callback) callback(false);
}
};
SP.clear = function(key, store = this.current) {
if (!this.db) {
this.init();
return this.queue.push(['clear', store]);
}
this.db
.transaction(store, "readwrite")
.objectStore(store).clear();
};
})();

View file

@ -4,46 +4,46 @@
(function() {
gapp.register('data.local');
gapp.register('data.local');
let data = self.data = self.data || {};
if (data.Local) return;
let data = self.data = self.data || {};
if (data.Local) return;
function Local() {
this.__data__ = {};
this.__mem__ = true;
}
function Local() {
this.__data__ = {};
this.__mem__ = true;
}
var LS = Local.prototype;
var LS = Local.prototype;
LS.getItem = function(key) {
return this[key];
};
LS.getItem = function(key) {
return this[key];
};
LS.setItem = function(key, val) {
this.__data__[key] = val;
this[key] = val;
};
LS.setItem = function(key, val) {
this.__data__[key] = val;
this[key] = val;
};
LS.removeItem = function(key) {
delete this.__data__[key];
};
LS.removeItem = function(key) {
delete this.__data__[key];
};
LS.clear = function() {
this.__data__ = {};
};
LS.clear = function() {
this.__data__ = {};
};
try {
let local = data.Local = self.localStorage;
let testkey = '__test';
local.setItem(testkey, 1);
local.getItem(testkey);
local.removeItem(testkey);
} catch (e) {
data.Local = new Local();
let msg = "in private or restricted browsing mode. local storage blocked. application may not function properly.";
console.log(msg);
alert(msg);
}
try {
let local = data.Local = self.localStorage;
let testkey = '__test';
local.setItem(testkey, 1);
local.getItem(testkey);
local.removeItem(testkey);
} catch (e) {
data.Local = new Local();
let msg = "in private or restricted browsing mode. local storage blocked. application may not function properly.";
console.log(msg);
alert(msg);
}
})();