web sqlを使って、local storgeを適応して保存します。
13372 ワード
IPADのlocastorgeは上限が5 Mしかないので、足りないです。今はwebsqlで代用したいです。最初の設計はコールバック方式を考慮していません。結果コードの修正が多いです。httml 5 websql/file appiの呼び出しがあまり好きではありません。phonegapのプラグインはcalbackポインタを使っています。これは理解できます。純粋なjsはなぜこのように設計されていますか?コードを貼り付けます
注意:XDBメソッドを呼び出す時、setTimeoutを加えると、これはhackとなります。web sqlを使う前に、文字列の圧縮を行うという考えが浮かんでいます。効果もいいです。圧縮率は50%以上で、jsの圧縮類も貼っています。
アップルはios設備でhttml 5をサポートしていますが、個人的には信じられません。
/**
* Begin class defination XDB : Web sql
*/
var XDB = {
db: null,
init: function(dbName, version, dbDisplayName, size){
if(window.openDatabase)
this.db = openDatabase(dbName, version, dbDisplayName, size);
},
exe: function(sql, args, callback){
if(!this.db){
X.log('Web sql not support!');
return;
}
this.db.transaction(function(tx){
if(!sql.contains('t_key_val'))
X.log('Web sql exe : ' + sql + ' || ' + (args ? args.join(',') : 'null'));
tx.executeSql(sql, args, function(tx, results){
if(callback)
callback(results);
}, function(tx, err){
// SQLError
X.log('Web sql execute error: ' + err.message);
});
});
},
exeSqlLl: function(sqlLl, pre, suf){
if(!this.db){
X.log('Web sql not support!');
return;
}
pre = pre || '';
suf = suf || '';
this.db.transaction(function(tx){
X.log('Web sql exe : ' + sqlLl.length);
var savedLog = false;
var i = 0;
for (; i < sqlLl.length; i++){
var sql = sqlLl[i];
if(sql.trim()){
sql = pre + sql + suf;
tx.executeSql(sql, null, null, function(tx, err){
// SQLError
X.log('Web sql execute error: ' + err.message);
if(!savedLog){
X.logDb('Web sql execute error: ' + err.message);
X.logDb('Web sql sql: ' + sql);
savedLog = true;
}
});
}
}
});
},
trans: function(fn){
if(!this.db){
X.log('Web sql not support!');
return;
}
this.db.transaction(fn);
},
// crud
add: function(data, table){
var keys = _.keys(data);
var str1 = keys.join(',');
var str2 = _.map(keys, function(it){return '?';}).join(',');
var sql = 'insert into {0} ({1}) values ({2})';
sql = sql.format(table, str1, str2);
var args = _.values(data);
this.exe(sql, args)
},
del: function(data, table){
var keys = _.keys(data);
var strClause = _.map(keys, function(it){
return it + ' = ?';
}).join(' and ');
var sql = 'delete from {0} where {1}';
sql = sql.format(table, strClause);
var args = _.values(data);
this.exe(sql, args)
},
update: function(data, dataClause, table){
var strSet = _.map(_.keys(data), function(it){
return it + ' = ?';
}).join(', ');
var argsSet = _.values(data);
var strClause = _.map(_.keys(dataClause), function(it){
return it + ' = ?';
}).join(' and ');
var argsClause = _.values(dataClause);
var sql = 'update {0} set {1} where {2}';
sql = sql.format(table, strSet, strClause);
this.exe(sql, argsSet.merge(argsClause))
},
queryItem: function(sql, args, callback){
this.exe(sql, args, function(results){
if(callback){
if(results.rows.length > 0){
var item = results.rows.item(0);
if(!sql.contains('t_key_val'))
X.log('Query resultset item : ' + JSON.stringify(item));
callback(item);
}else{
callback(null);
}
}
});
},
query: function(sql, args, callback){
this.exe(sql, args, function(results){
X.log('Query resultset size : ' + results.rows.length);
if(callback)
callback(results.rows);
});
},
queryAndMap: function(sql, args, callback, callback2){
this.query(sql, args, function(rows){
if(callback){
var i = 0;
for (; i < rows.length; i++){
var record = rows.item(i);
callback(record, i);
}
}
if(callback2)
callback2(rows);
});
},
pi: function(sql, args, cp, npp, callback){
var pager = new XPager(cp, npp, 0);
var countSql = 'select count(1) as rowCount from ({0})'.format(sql);
var subSql = 'select * from ({0}) limit {1}, {2}'.format(sql, pager.getStart(), npp);
var _this = this;
this.query(countSql, args, function(rows){
pager.rowCount = rows.item(0)['rowCount'];
_this.query(subSql, args, function(rows){
if(callback)
callback(pager, rows);
});
});
},
piAndMap: function(sql, args, cp, npp, callback, callback2){
this.pi(sql, args, cp, npp, function(pager, rows){
if(callback){
var i = 0;
for (; i < rows.length; i++){
var record = rows.item(i);
callback(record, i);
}
if(callback2)
callback2(pager);
}
});
},
dump : ''
};
// HTML5
// , db
var XLocal = {
storage: null,
keyGlobal: null,
init: function(key){
if(window.localStorage){
this.storage = window.localStorage;
if(key){
this.keyGlobal = key;
}
}else{
X.log('Web localStorage api not support!');
}
},
clear: function(){
if(!this.storage){
X.log('Web localStorage api not support!');
return;
}
if(this.keyGlobal){
this.storage.removeItem(this.keyGlobal);
}else{
this.storage.clear();
}
},
get: function(key, unpack){
if(!this.storage){
X.log('Web localStorage api not support!');
return;
}
if(!this.keyGlobal){
var str = this.storage[key];
if(!str || 'undefined' == str || 'null' == str)
return null
if(unpack)
str = LzwCN.unpack(str);
return JSON.parse(str);
}else{
var str = this.storage[this.keyGlobal];
if(str){
var item = JSON.parse(str);
return item ? item[key] : null;
}
}
},
put: function(key, val, pack){
if(!this.storage){
X.log('Web localStorage api not support!');
return;
}
X.log('Web localStorage put ' + key);
if(!this.keyGlobal){
// ,ipad localstorage ?
// http://stackoverflow.com/questions/5887326/is-localstorage-reliable-on-an-ipad
this.remove(key);
var str = JSON.stringify(val);
if(pack)
str = LzwCN.pack(str);
this.storage[key] = str;
}else{
this.remove(key);
var item = {};
var str = this.storage[this.keyGlobal];
if(str)
item = JSON.parse(str);
item[key] = val;
this.storage[this.keyGlobal] = JSON.stringify(item);
}
},
remove: function(key){
if(!this.storage){
X.log('Web localStorage api not support!');
return;
}
X.log('Web localStorage remove ' + key);
if(!this.keyGlobal){
this.storage.removeItem(key);
}else{
var str = this.storage[this.keyGlobal];
if(str){
var item = JSON.parse(str);
if(item){
item[key] = null;
this.storage[this.keyGlobal] = JSON.stringify(item);
}
}
}
},
dump: ''
};
var XLocalDB = {
init: function(){
XDB.exe('create table if not exists t_key_val(k varchar,v varchar)');
},
clear: function(){
var sql = 'delete from t_key_val';
setTimeout(function(){
XDB.exe(sql);
}, 100);
},
/*
XLocalDB.clear()
XLocalDB.put('y', {a: 'xx'})
XLocalDB.get('y', function(item){
X.log(item);
});
*/
get: function(key, fn){
var sql = 'select v from t_key_val where k = ?';
var sqlArgs = [key];
XDB.queryItem(sql, sqlArgs, function(item){
if(!item){
if(fn)
fn(null);
}else{
var src = item.v;
if(src){
src = LzwCN.unpack(src);
var val = JSON.parse(src);
if(fn)
fn(val);
}else{
if(fn)
fn(null);
}
}
});
},
put: function(key, val){
X.log('Web DB put ' + key);
var src = JSON.stringify(val);
src = LzwCN.pack(src);
var item = {k: key, v: src};
setTimeout(function(){
XDB.add(item, 't_key_val');
}, 100);
},
remove: function(key){
X.log('Web DB remove ' + key);
var item = {k: key};
setTimeout(function(){
XDB.del(item, 't_key_val');
}, 100);
},
dump: ''
};
注意:XDBメソッドを呼び出す時、setTimeoutを加えると、これはhackとなります。web sqlを使う前に、文字列の圧縮を行うという考えが浮かんでいます。効果もいいです。圧縮率は50%以上で、jsの圧縮類も貼っています。
var LzwCN = {};
LzwCN.compress = function(text){
var result = [];
for(var n = 0; n < text.length; n++){
var c = text.charCodeAt(n);
if (c < 128){
result.push(String.fromCharCode(c));
}else if (c > 127 && c < 2048){
result.push(String.fromCharCode((c >> 6) | 192));
result.push(String.fromCharCode((c & 63) | 128));
}else{
result.push(String.fromCharCode((c >> 12) | 224));
result.push(String.fromCharCode(((c >> 6) & 63) | 128));
result.push(String.fromCharCode((c & 63) | 128));
}
}
return result.join('');
};
LzwCN.decompress = function(text){
var result = [];
var i = 0, c1 = 0, c2 = 0, c3 = 0;
while(i < text.length){
c1 = text.charCodeAt(i);
if (c1 < 128){
result.push(String.fromCharCode(c1));
i++;
}else if (c1 > 191 && c1 < 224){
c2 = text.charCodeAt(i + 1);
result.push(String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)));
i += 2;
}else{
c2 = text.charCodeAt(i + 1);
c3 = text.charCodeAt(i + 2);
result.push(String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
i += 3;
}
}
return result.join('');
};
LzwCN.pack = function(str){
var result = [];
var rstr = this.compress(str);
var i = 0,
size = 0,
xstr = '',
chars = 256,
dict = [];
for(i = 0; i < chars; i++){
dict[String(i)] = i;
}
var splitted = rstr.split('');
var buffer = [];
var current = '';
for(i = 0; i <= splitted.length; i++){
current = new String(splitted[i]);
xstr = (buffer.length == 0) ? String(current.charCodeAt(0)) : (buffer.join('-') + '-' + String(current.charCodeAt(0)));
if (dict[xstr] !== undefined){
buffer.push(current.charCodeAt(0));
}else{
result.push(String.fromCharCode(dict[buffer.join('-')]));
dict[xstr] = chars;
chars++;
buffer = [current.charCodeAt(0)];
}
}
return result.join('');
};
LzwCN.unpack = function(str){
var i,
chars = 256,
dict = [];
for(i = 0; i < chars; i++){
dict[i] = String.fromCharCode(i);
}
var original = new String(str);
var splitted = original.split('');
var buffer = '';
var chain = '';
var result = [];
for(i = 0; i < splitted.length; i++){
var code = original.charCodeAt(i);
var current = dict[code];
if(buffer == ''){
buffer = current;
result.push(current);
}else{
if(code <= 255){
result.push(current);
chain = buffer + current;
dict[chars] = chain;
chars++;
buffer = current;
}else{
chain = dict[code];
if(chain == null){
chain = buffer + buffer.slice(0, 1);
}
result.push(chain);
dict[chars] = buffer + chain.slice(0, 1);
chars++;
buffer = chain;
}
}
}
return this.decompress(result.join(''));
};
アップルはios設備でhttml 5をサポートしていますが、個人的には信じられません。