mirror of
https://github.com/moparisthebest/PhoneGap-SQLitePlugin-Android
synced 2024-11-13 12:35:09 -05:00
Initial adaptation of Lawnchair adapter from original WebKit version
This commit is contained in:
parent
90dadd6619
commit
813ba2b8b7
340
DroidGap/lawnchair-adapter-test/www/SQLitePlugin.js
Normal file
340
DroidGap/lawnchair-adapter-test/www/SQLitePlugin.js
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is purely for the Android 1.5/1.6 HTML 5 Storage
|
||||
* I was hoping that Android 2.0 would deprecate this, but given the fact that
|
||||
* most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* SQL result set object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Rows = function() {
|
||||
this.resultSet = []; // results array
|
||||
this.length = 0; // number of rows
|
||||
};
|
||||
|
||||
/**
|
||||
* Get item from SQL result set
|
||||
*
|
||||
* @param row The row number to return
|
||||
* @return The row object
|
||||
*/
|
||||
DDB_Rows.prototype.item = function(row) {
|
||||
return this.resultSet[row];
|
||||
};
|
||||
|
||||
/**
|
||||
* SQL result set that is returned to user.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Result = function() {
|
||||
this.rows = new DDB_Rows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage object that is called by native code when performing queries.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB = function() {
|
||||
this.queryQueue = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query is complete.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB.prototype.completeQuery = function(id, data) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
|
||||
// Save query results
|
||||
var r = new DDB_Result();
|
||||
r.rows.resultSet = data;
|
||||
r.rows.length = data.length;
|
||||
try {
|
||||
if (typeof query.successCallback === 'function') {
|
||||
query.successCallback(query.tx, r);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user success callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryComplete(id);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query fails
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param reason Error message
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB.prototype.fail = function(reason, id) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
tx.queryList = {};
|
||||
|
||||
try {
|
||||
if (typeof query.errorCallback === 'function') {
|
||||
query.errorCallback(query.tx, reason);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user error callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryFailed(id, reason);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mycreateUUID = function() {
|
||||
return myUUIDcreatePart(4) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(2) + '-' +
|
||||
myUUIDcreatePart(6);
|
||||
};
|
||||
|
||||
myUUIDcreatePart = function(length) {
|
||||
var uuidpart = "";
|
||||
var i, uuidchar;
|
||||
for (i=0; i<length; i++) {
|
||||
uuidchar = parseInt((Math.random() * 256),0).toString(16);
|
||||
if (uuidchar.length === 1) {
|
||||
uuidchar = "0" + uuidchar;
|
||||
}
|
||||
uuidpart += uuidchar;
|
||||
}
|
||||
return uuidpart;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SQL query object
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @constructor
|
||||
* @param tx The transaction object that this query belongs to
|
||||
*/
|
||||
var DDB_Query = function(tx) {
|
||||
|
||||
// Set the id of the query
|
||||
this.id = mycreateUUID();
|
||||
|
||||
// Add this query to the queue
|
||||
dddb.queryQueue[this.id] = this;
|
||||
|
||||
// Init result
|
||||
this.resultSet = [];
|
||||
|
||||
// Set transaction that this query belongs to
|
||||
this.tx = tx;
|
||||
|
||||
// Add this query to transaction list
|
||||
this.tx.queryList[this.id] = this;
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Transaction object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DDB_Tx = function() {
|
||||
|
||||
// Set the id of the transaction
|
||||
this.id = mycreateUUID();
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
// Query list
|
||||
this.queryList = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as complete.
|
||||
* If all queries are complete, call the user's transaction success callback.
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DDB_Tx.prototype.queryComplete = function(id) {
|
||||
delete this.queryList[id];
|
||||
|
||||
// If no more outstanding queries, then fire transaction success
|
||||
if (this.successCallback) {
|
||||
var count = 0;
|
||||
var i;
|
||||
for (i in this.queryList) {
|
||||
if (this.queryList.hasOwnProperty(i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count === 0) {
|
||||
try {
|
||||
this.successCallback();
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user success callback: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as failed.
|
||||
*
|
||||
* @param id Query id
|
||||
* @param reason Error message
|
||||
*/
|
||||
DDB_Tx.prototype.queryFailed = function(id, reason) {
|
||||
|
||||
// The sql queries in this transaction have already been run, since
|
||||
// we really don't have a real transaction implemented in native code.
|
||||
// However, the user callbacks for the remaining sql queries in transaction
|
||||
// will not be called.
|
||||
this.queryList = {};
|
||||
|
||||
if (this.errorCallback) {
|
||||
try {
|
||||
this.errorCallback(reason);
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user error callback: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute SQL statement
|
||||
*
|
||||
* @param sql SQL statement to execute
|
||||
* @param params Statement parameters
|
||||
* @param successCallback Success callback
|
||||
* @param errorCallback Error callback
|
||||
*/
|
||||
DDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
|
||||
|
||||
// Init params array
|
||||
if (typeof params === 'undefined') {
|
||||
params = [];
|
||||
}
|
||||
|
||||
// Create query and add to queue
|
||||
var query = new DDB_Query(this);
|
||||
dddb.queryQueue[query.id] = query;
|
||||
|
||||
// Save callbacks
|
||||
query.successCallback = successCallback;
|
||||
query.errorCallback = errorCallback;
|
||||
|
||||
// Call native code
|
||||
PhoneGap.exec(null, null, "SQLitePlugin", "executeSql", [sql, params, query.id]);
|
||||
};
|
||||
|
||||
var DatabaseShell = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
* Does not support rollback in event of failure.
|
||||
*
|
||||
* @param process {Function} The transaction function
|
||||
* @param successCallback {Function}
|
||||
* @param errorCallback {Function}
|
||||
*/
|
||||
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
|
||||
var tx = new DDB_Tx();
|
||||
tx.successCallback = successCallback;
|
||||
tx.errorCallback = errorCallback;
|
||||
try {
|
||||
process(tx);
|
||||
} catch (e) {
|
||||
console.log("Transaction error: "+e);
|
||||
if (tx.errorCallback) {
|
||||
try {
|
||||
tx.errorCallback(e);
|
||||
} catch (ex) {
|
||||
console.log("Transaction error calling user error callback: "+e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open database
|
||||
*
|
||||
* @param name Database name
|
||||
* @param version Database version
|
||||
* @param display_name Database display name
|
||||
* @param size Database size in bytes
|
||||
* @return Database object
|
||||
*/
|
||||
var DDB_openDatabase = function(name, version, display_name, size) {
|
||||
console.log("open database " + name + " ... typeof " + typeof(PhoneGap.exec));
|
||||
PhoneGap.exec(null, null, "SQLitePlugin", "openDatabase", [name, version, display_name, size]);
|
||||
//cordova.exec(null, null, "SQLitePlugin", "openDatabase", [name, version, display_name, size]);
|
||||
var db = new DatabaseShell();
|
||||
return db;
|
||||
};
|
||||
|
||||
/**
|
||||
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
|
||||
* TODO: Do similar for sessionStorage.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
window.my_openDatabase = function(name, version, desc, size){
|
||||
window.dddb = new DDB();
|
||||
return DDB_openDatabase(name, version, desc, size);
|
||||
}
|
||||
|
4841
DroidGap/lawnchair-adapter-test/www/cordova-1.5.0.js
vendored
Normal file
4841
DroidGap/lawnchair-adapter-test/www/cordova-1.5.0.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
181
DroidGap/lawnchair-adapter-test/www/index.html
Normal file
181
DroidGap/lawnchair-adapter-test/www/index.html
Normal file
@ -0,0 +1,181 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=320; user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>PhoneGap</title>
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8">
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="SQLitePlugin.js"></script>
|
||||
|
||||
<script src="lib/qunit.js"></script>
|
||||
<script src="lib/json2.js"></script>
|
||||
<script src="lib/lawnchair.js"></script>
|
||||
|
||||
<script src="webkit-sqlite.js"></script>
|
||||
<script src="lawnchair-spec.js"></script>
|
||||
|
||||
<!--
|
||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||
-->
|
||||
|
||||
|
||||
<script type="text/javascript" charset="utf-8" >
|
||||
|
||||
|
||||
|
||||
// autostart seems to be a little eager
|
||||
QUnit.config.autostart = false
|
||||
|
||||
// kill qunit saves
|
||||
try{ sessionStorage.clear(); } catch(e){}
|
||||
|
||||
var store;
|
||||
|
||||
function startTests() {
|
||||
|
||||
// allow restriction of adapter in URL (e.g., ?adapter=ie-userdata)
|
||||
var allowed = /adapter=([-\w]+)/.exec(window.location.href),
|
||||
adapters = Lawnchair.adapters,
|
||||
i;
|
||||
|
||||
if (allowed) {
|
||||
for (i = 0; i < adapters.length; ) {
|
||||
if (adapters[i].adapter == allowed[1]) {
|
||||
i++;
|
||||
} else {
|
||||
adapters.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
if (adapters.length == 0) {
|
||||
alert("no such adapter: " + allowed[1]);
|
||||
}
|
||||
|
||||
if (!adapters[0].valid()) {
|
||||
alert("adapter " + allowed[1] + " is not valid in this environment");
|
||||
}
|
||||
}
|
||||
|
||||
// kickup the chair
|
||||
store = new Lawnchair({name:'tests'}, function(){
|
||||
QUnit.start()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function start1() {
|
||||
|
||||
document.addEventListener("deviceready", startTests, false);
|
||||
}
|
||||
|
||||
function init1test() {
|
||||
//alert("alert 0");
|
||||
}
|
||||
|
||||
// Wait for PhoneGap to load
|
||||
//
|
||||
document.addEventListener("deviceready", onDeviceReady, false);
|
||||
|
||||
// PhoneGap is ready
|
||||
//
|
||||
function onDeviceReady() {
|
||||
var db = window.my_openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
|
||||
|
||||
db.transaction(function(tx) {
|
||||
|
||||
tx.executeSql('DROP TABLE IF EXISTS test_table');
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS test_table (id integer primary key, data text, data_num integer)');
|
||||
|
||||
|
||||
return tx.executeSql("INSERT INTO test_table (data, data_num) VALUES (?,?)", ["test", 100], function(tx, res) {
|
||||
//console.log("insertId: " + res.insertId + " -- probably 1");
|
||||
//console.log("rowsAffected: " + res.rowsAffected + " -- should be 1");
|
||||
|
||||
tx.executeSql("select count(id) as cnt from test_table;", [], function(tx, res) {
|
||||
console.log("rows.length: " + res.rows.length + " -- should be 1");
|
||||
return console.log("rows[0].cnt: " + res.rows.item(0).cnt + " -- should be 1");
|
||||
});
|
||||
|
||||
}, function(e) {
|
||||
return console.log("ERROR: " + e.message);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Populate the database
|
||||
//
|
||||
function populateDB(tx) {
|
||||
alert("a 3");
|
||||
tx.executeSql('DROP TABLE IF EXISTS DEMO');
|
||||
alert("a 4");
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
|
||||
alert("a 5");
|
||||
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');
|
||||
alert("a 6");
|
||||
tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');
|
||||
alert("a 7");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Transaction error callback
|
||||
//
|
||||
function errorCB(tx, err) {
|
||||
alert("Error processing SQL: "+err);
|
||||
}
|
||||
|
||||
// Transaction success callback
|
||||
//
|
||||
function successCB() {
|
||||
alert("success!");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="start1()">
|
||||
<h1 id="qunit-header">Lawnchair Spec</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
</body>
|
||||
|
||||
|
||||
<!--
|
||||
<body onload="init1test();" id="stage" class="theme">
|
||||
<h1>Welcome to PhoneGap!</h1>
|
||||
<h2>this file is located at assets/www/index.html</h2>
|
||||
<div id="info">
|
||||
<h4>Platform: <span id="platform"> </span>, Version: <span id="version"> </span></h4>
|
||||
<h4>UUID: <span id="uuid"> </span>, Name: <span id="name"> </span></h4>
|
||||
<h4>Width: <span id="width"> </span>, Height: <span id="height">
|
||||
</span>, Color Depth: <span id="colorDepth"></span></h4>
|
||||
</div>
|
||||
<dl id="accel-data">
|
||||
<dt>X:</dt><dd id="x"> </dd>
|
||||
<dt>Y:</dt><dd id="y"> </dd>
|
||||
<dt>Z:</dt><dd id="z"> </dd>
|
||||
</dl>
|
||||
<a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
|
||||
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
|
||||
<a href="tel:411" class="btn large">Call 411</a>
|
||||
<a href="#" class="btn large" onclick="beep();">Beep</a>
|
||||
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
|
||||
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
|
||||
<a href="#" class="btn large" onclick="get_contacts();">Get Phone's Contacts</a>
|
||||
<a href="#" class="btn large" onclick="check_network();">Check Network</a>
|
||||
<div id="viewport" class="viewport" style="display: none;">
|
||||
<img style="width:60px;height:60px" id="test_img" src="" />
|
||||
</div>
|
||||
</body>
|
||||
-->
|
||||
</html>
|
429
DroidGap/lawnchair-adapter-test/www/lawnchair-spec.js
Executable file
429
DroidGap/lawnchair-adapter-test/www/lawnchair-spec.js
Executable file
@ -0,0 +1,429 @@
|
||||
module('Lawnchair construction/destruction', {
|
||||
setup:function() {
|
||||
},
|
||||
teardown:function() {
|
||||
}
|
||||
});
|
||||
|
||||
test('ctor requires callbacks in each form', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(6);
|
||||
|
||||
// raise exception if no ctor callback is supplied
|
||||
try {
|
||||
var lc2 = new Lawnchair();
|
||||
} catch(e) {
|
||||
ok(true, 'exception raised if no callback supplied to init');
|
||||
}
|
||||
try {
|
||||
var lc3 = new Lawnchair({}, {});
|
||||
} catch(e) {
|
||||
ok(true, 'exception raised if no callback supplied to init, but two args are present');
|
||||
}
|
||||
try {
|
||||
var lc3 = new Lawnchair({});
|
||||
} catch(e) {
|
||||
ok(true, 'exception raised if no callback supplied to init, but one arg is present');
|
||||
}
|
||||
|
||||
var lc = new Lawnchair({name:store.name}, function(ref) {
|
||||
ok(true, 'should call passed in callback when using obj+function ctor form')
|
||||
equals(this, ref, "lawnchair callback scoped to lawnchair instance")
|
||||
equals(ref, this, "lawnchair passes self into callback too")
|
||||
QUnit.start()
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
test('independent data stores', function() {
|
||||
|
||||
var store1 = new Lawnchair({name: "store1"}, function() {});
|
||||
|
||||
store1 .save({key: 'apple', quantity: 3}, function() {
|
||||
|
||||
var store2 = new Lawnchair({name: "store2"}, function() {});
|
||||
|
||||
store1.all(function(r) {
|
||||
equals(r.length, 1);
|
||||
});
|
||||
|
||||
store2.all(function(r) {
|
||||
equals(r.length, 0);
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
**/
|
||||
|
||||
module('all()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
|
||||
// I like to make all my variables globals. Starting a new trend.
|
||||
me = {name:'brian', age:30};
|
||||
store.nuke(function() { QUnit.start(); });
|
||||
},
|
||||
teardown:function() {
|
||||
me = null;
|
||||
}
|
||||
})
|
||||
|
||||
test('chainable', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(1);
|
||||
|
||||
same(store.all(function(r) { QUnit.start(); }), store, 'should be chainable (return itself)');
|
||||
})
|
||||
|
||||
test('full callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(4);
|
||||
|
||||
store.all(function(r) {
|
||||
ok(true, 'calls callback');
|
||||
ok(r instanceof Array, 'should provide array as parameter');
|
||||
equals(r.length, 0, 'parameter should initially have zero length');
|
||||
same(this, store, '"this" should be scoped to the lawnchair object inside callback');
|
||||
QUnit.start();
|
||||
});
|
||||
})
|
||||
|
||||
test('adding, nuking and size tests', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save(me, function() {
|
||||
store.all(function(r) {
|
||||
equals(r.length, 1, 'parameter should have length 1 after saving a single record');
|
||||
store.nuke(function() {
|
||||
store.all(function(r) {
|
||||
equals(r.length, 0, 'parameter should have length 0 after nuking');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
test( 'shorthand callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.all('ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();');
|
||||
|
||||
// Is this test block necessary?
|
||||
//
|
||||
// var tmp = new Lawnchair({name:'temps', record:'tmp'}, function(){
|
||||
// QUnit.start()
|
||||
// var Temps = this;
|
||||
// equals(this, Temps, 'this is bound to Lawnchair')
|
||||
// QUnit.stop()
|
||||
// Temps.all('ok(temps, "this.name is passed to all callback"); QUnit.start()')
|
||||
// })
|
||||
})
|
||||
|
||||
test('scoped variable in shorthand callback', function() {
|
||||
QUnit.expect(1);
|
||||
QUnit.stop();
|
||||
|
||||
// FIXME fkn qunit being weird here... expect(1)
|
||||
var tmp = new Lawnchair({name:'temps', record:'tmp'}, function() {
|
||||
this.nuke(function() {
|
||||
this.save({a:1}, function() {
|
||||
this.each('ok(tmp, "this.record is passed to each callback"); QUnit.start()')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
module('nuke()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
store.nuke(function() {
|
||||
QUnit.start()
|
||||
});
|
||||
},
|
||||
teardown:function() {
|
||||
}
|
||||
})
|
||||
|
||||
test( 'chainable', function() {
|
||||
QUnit.expect(1);
|
||||
QUnit.stop()
|
||||
|
||||
same(store.nuke(function() { QUnit.start() }), store, 'should be chainable');
|
||||
})
|
||||
|
||||
test( 'full callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.nuke(function() {
|
||||
ok(true, "should call callback in nuke");
|
||||
same(this, store, '"this" should be scoped to the Lawnchair instance');
|
||||
QUnit.start();
|
||||
});
|
||||
})
|
||||
|
||||
test( 'shorthand callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.nuke('ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();');
|
||||
})
|
||||
|
||||
module('save()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
|
||||
// I like to make all my variables globals. Starting a new trend.
|
||||
me = {name:'brian', age:30};
|
||||
store.nuke(function() { QUnit.start(); });
|
||||
},
|
||||
teardown:function() {
|
||||
me = null;
|
||||
}
|
||||
})
|
||||
|
||||
test( 'chainable', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(1);
|
||||
|
||||
same(store.save(me, function() { QUnit.start(); }), store, 'should be chainable');
|
||||
})
|
||||
|
||||
test( 'full callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save(me, function(it) {
|
||||
ok(true, 'should call passed in callback');
|
||||
same(it, me, 'should pass in original saved object in callback');
|
||||
QUnit.start();
|
||||
});
|
||||
})
|
||||
|
||||
test( 'shorthand callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save(me, 'ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();');
|
||||
})
|
||||
|
||||
test( 'saving objects', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(1);
|
||||
|
||||
store.save(me, function() {
|
||||
store.save({key:"something", value:"else"}, function(r) {
|
||||
store.all(function(r) {
|
||||
equals(r.length, 2, 'after saving two keys, num. records should equal to 2');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
test( 'save without callback', function() {
|
||||
|
||||
QUnit.stop();
|
||||
QUnit.expect(1);
|
||||
|
||||
store.save(me, function(obj) {
|
||||
var key = obj.key;
|
||||
store.save(obj);
|
||||
equals(obj.key, key, "save without callback retains key");
|
||||
QUnit.start();
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
module('batch()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
|
||||
// I like to make all my variables globals. Starting a new trend.
|
||||
me = {name:'brian', age:30};
|
||||
store.nuke(function() { QUnit.start(); });
|
||||
},
|
||||
teardown:function() {
|
||||
me = null;
|
||||
}
|
||||
})
|
||||
|
||||
test('batch insertion', function(){
|
||||
QUnit.expect(3);
|
||||
QUnit.stop();
|
||||
|
||||
ok(store.batch, 'batch implemented');
|
||||
equals(store.batch([]), store, 'chainable')
|
||||
|
||||
store.batch([{i:1},{i:2}], function() {
|
||||
store.all(function(r){
|
||||
equals(r.length, 2, 'should be two records from batch insert with array of two objects');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
test( 'full callback syntax', function() {
|
||||
QUnit.stop(500);
|
||||
QUnit.expect(2);
|
||||
|
||||
store.batch([{j:'k'}], function() {
|
||||
ok(true, 'callback called with full syntax');
|
||||
same(this, store, '"this" should be the LAwnchair instance');
|
||||
QUnit.start();
|
||||
})
|
||||
})
|
||||
|
||||
test( 'shorthand callback syntax', function() {
|
||||
QUnit.stop(500);
|
||||
QUnit.expect(2);
|
||||
|
||||
store.batch([{o:'k'}], 'ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();')
|
||||
})
|
||||
|
||||
module('get()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
|
||||
// I like to make all my variables globals. Starting a new trend.
|
||||
me = {name:'brian', age:30};
|
||||
store.nuke(function() { QUnit.start(); });
|
||||
},
|
||||
teardown:function() {
|
||||
me = null;
|
||||
}
|
||||
});
|
||||
|
||||
test( 'should it be chainable?', function() {
|
||||
QUnit.expect(1);
|
||||
QUnit.stop();
|
||||
|
||||
equals(store.get('foo', function() { QUnit.start(); }), store, 'get chainable');
|
||||
});
|
||||
|
||||
test('get functionality', function() {
|
||||
QUnit.expect(4);
|
||||
QUnit.stop();
|
||||
|
||||
store.save({key:'xyz', name:'tim'}, function() {
|
||||
store.get('xyz', function(r) {
|
||||
equals(r.key, 'xyz', 'should return key in loaded object');
|
||||
equals(r.name, 'tim', 'should return proper object when calling get with a key');
|
||||
store.get('doesntexist', function(s) {
|
||||
ok(true, 'should call callback even for non-existent key');
|
||||
equals(s, null, 'should return null for non-existent key');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('get batch functionality', function() {
|
||||
QUnit.expect(3);
|
||||
QUnit.stop(500);
|
||||
|
||||
var t = [{key:'test-get'},{key:'test-get-1'}]
|
||||
store.batch(t, function() {
|
||||
this.get(['test-get','test-get-1'], function(r) {
|
||||
equals(r[0].key, 'test-get', "get first object");
|
||||
equals(r[1].key, 'test-get-1', "get second object");
|
||||
equals(r.length, t.length, "should batch get")
|
||||
QUnit.start()
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
test( 'full callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.get('somekey', function(r){
|
||||
ok(true, 'callback got called');
|
||||
same(this, store, '"this" should be teh Lawnchair instance');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
|
||||
test('short callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.get('somekey', 'ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();');
|
||||
});
|
||||
|
||||
module('remove()', {
|
||||
setup:function() {
|
||||
QUnit.stop();
|
||||
|
||||
// I like to make all my variables globals. Starting a new trend.
|
||||
me = {name:'brian', age:30};
|
||||
store.nuke(function() { QUnit.start(); });
|
||||
},
|
||||
teardown:function() {
|
||||
me = null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test( 'chainable', function() {
|
||||
QUnit.expect(1);
|
||||
QUnit.stop();
|
||||
|
||||
store.save({key:'me', name:'brian'}, function() {
|
||||
same(store.remove('me', function() {
|
||||
QUnit.start();
|
||||
}), store, 'should be chainable');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test( 'full callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save({key:'somekey', name:'something'}, function() {
|
||||
store.remove('somekey', function(r){
|
||||
ok(true, 'callback got called');
|
||||
same(this, store, '"this" should be teh Lawnchair instance');
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('short callback syntax', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save({key:'somekey', name:'something'}, function() {
|
||||
store.remove('somekey', 'ok(true, "shorthand syntax callback gets evaled"); same(this, store, "`this` should be scoped to the Lawnchair instance"); QUnit.start();');
|
||||
});
|
||||
});
|
||||
|
||||
// FIXME need to add tests for batch deletion
|
||||
test( 'remove functionality', function() {
|
||||
QUnit.stop();
|
||||
QUnit.expect(2);
|
||||
|
||||
store.save({name:'joni'}, function(r) {
|
||||
//store.find("r.name == 'joni'", function(r){
|
||||
store.remove(r, function(r) {
|
||||
store.all(function(all) {
|
||||
equals(all.length, 0, "should have length 0 after saving, finding, and removing a record using entire object");
|
||||
store.save({key:'die', name:'dudeman'}, function(r) {
|
||||
store.remove('die', function(r){
|
||||
store.all(function(rec) {
|
||||
equals(rec.length, 0, "should have length 0 after saving and removing by string key");
|
||||
QUnit.start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
//});
|
||||
});
|
||||
});
|
482
DroidGap/lawnchair-adapter-test/www/lib/json2.js
Normal file
482
DroidGap/lawnchair-adapter-test/www/lib/json2.js
Normal file
@ -0,0 +1,482 @@
|
||||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2010-03-20
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
*/
|
||||
|
||||
/*jslint evil: true, strict: false */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
if (!this.JSON) {
|
||||
this.JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf()) ?
|
||||
this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z' : null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ?
|
||||
'"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string' ? c :
|
||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' :
|
||||
'"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0 ? '[]' :
|
||||
gap ? '[\n' + gap +
|
||||
partial.join(',\n' + gap) + '\n' +
|
||||
mind + ']' :
|
||||
'[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
k = rep[i];
|
||||
if (typeof k === 'string') {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0 ? '{}' :
|
||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
||||
mind + '}' : '{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/.
|
||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
151
DroidGap/lawnchair-adapter-test/www/lib/lawnchair.js
Normal file
151
DroidGap/lawnchair-adapter-test/www/lib/lawnchair.js
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Lawnchair!
|
||||
* ---
|
||||
* clientside json store
|
||||
*
|
||||
*/
|
||||
var Lawnchair = function (options, callback) {
|
||||
// ensure Lawnchair was called as a constructor
|
||||
if (!(this instanceof Lawnchair)) return new Lawnchair(options, callback);
|
||||
|
||||
// lawnchair requires json
|
||||
if (!JSON) throw 'JSON unavailable! Include http://www.json.org/json2.js to fix.'
|
||||
// options are optional; callback is not
|
||||
if (arguments.length <= 2 && arguments.length > 0) {
|
||||
callback = (typeof arguments[0] === 'function') ? arguments[0] : arguments[1];
|
||||
options = (typeof arguments[0] === 'function') ? {} : arguments[0];
|
||||
} else {
|
||||
throw 'Incorrect # of ctor args!'
|
||||
}
|
||||
// TODO perhaps allow for pub/sub instead?
|
||||
if (typeof callback !== 'function') throw 'No callback was provided';
|
||||
|
||||
// default configuration
|
||||
this.record = options.record || 'record' // default for records
|
||||
this.name = options.name || 'records' // default name for underlying store
|
||||
|
||||
// mixin first valid adapter
|
||||
var adapter
|
||||
// if the adapter is passed in we try to load that only
|
||||
if (options.adapter) {
|
||||
for (var i = 0, l = Lawnchair.adapters.length; i < l; i++) {
|
||||
if (Lawnchair.adapters[i].adapter === options.adapter) {
|
||||
adapter = Lawnchair.adapters[i].valid() ? Lawnchair.adapters[i] : undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// otherwise find the first valid adapter for this env
|
||||
}
|
||||
else {
|
||||
for (var i = 0, l = Lawnchair.adapters.length; i < l; i++) {
|
||||
adapter = Lawnchair.adapters[i].valid() ? Lawnchair.adapters[i] : undefined
|
||||
if (adapter) break
|
||||
}
|
||||
}
|
||||
|
||||
// we have failed
|
||||
if (!adapter) throw 'No valid adapter.'
|
||||
|
||||
// yay! mixin the adapter
|
||||
for (var j in adapter)
|
||||
this[j] = adapter[j]
|
||||
|
||||
// call init for each mixed in plugin
|
||||
for (var i = 0, l = Lawnchair.plugins.length; i < l; i++)
|
||||
Lawnchair.plugins[i].call(this)
|
||||
|
||||
// init the adapter
|
||||
this.init(options, callback)
|
||||
}
|
||||
|
||||
Lawnchair.adapters = []
|
||||
|
||||
/**
|
||||
* queues an adapter for mixin
|
||||
* ===
|
||||
* - ensures an adapter conforms to a specific interface
|
||||
*
|
||||
*/
|
||||
Lawnchair.adapter = function (id, obj) {
|
||||
// add the adapter id to the adapter obj
|
||||
// ugly here for a cleaner dsl for implementing adapters
|
||||
obj['adapter'] = id
|
||||
// methods required to implement a lawnchair adapter
|
||||
var implementing = 'adapter valid init keys save batch get exists all remove nuke'.split(' ')
|
||||
, indexOf = this.prototype.indexOf
|
||||
// mix in the adapter
|
||||
for (var i in obj) {
|
||||
if (indexOf(implementing, i) === -1) throw 'Invalid adapter! Nonstandard method: ' + i
|
||||
}
|
||||
// if we made it this far the adapter interface is valid
|
||||
// insert the new adapter as the preferred adapter
|
||||
Lawnchair.adapters.splice(0,0,obj)
|
||||
}
|
||||
|
||||
Lawnchair.plugins = []
|
||||
|
||||
/**
|
||||
* generic shallow extension for plugins
|
||||
* ===
|
||||
* - if an init method is found it registers it to be called when the lawnchair is inited
|
||||
* - yes we could use hasOwnProp but nobody here is an asshole
|
||||
*/
|
||||
Lawnchair.plugin = function (obj) {
|
||||
for (var i in obj)
|
||||
i === 'init' ? Lawnchair.plugins.push(obj[i]) : this.prototype[i] = obj[i]
|
||||
}
|
||||
|
||||
/**
|
||||
* helpers
|
||||
*
|
||||
*/
|
||||
Lawnchair.prototype = {
|
||||
|
||||
isArray: Array.isArray || function(o) { return Object.prototype.toString.call(o) === '[object Array]' },
|
||||
|
||||
/**
|
||||
* this code exists for ie8... for more background see:
|
||||
* http://www.flickr.com/photos/westcoastlogic/5955365742/in/photostream
|
||||
*/
|
||||
indexOf: function(ary, item, i, l) {
|
||||
if (ary.indexOf) return ary.indexOf(item)
|
||||
for (i = 0, l = ary.length; i < l; i++) if (ary[i] === item) return i
|
||||
return -1
|
||||
},
|
||||
|
||||
// awesome shorthand callbacks as strings. this is shameless theft from dojo.
|
||||
lambda: function (callback) {
|
||||
return this.fn(this.record, callback)
|
||||
},
|
||||
|
||||
// first stab at named parameters for terse callbacks; dojo: first != best // ;D
|
||||
fn: function (name, callback) {
|
||||
return typeof callback == 'string' ? new Function(name, callback) : callback
|
||||
},
|
||||
|
||||
// returns a unique identifier (by way of Backbone.localStorage.js)
|
||||
// TODO investigate smaller UUIDs to cut on storage cost
|
||||
uuid: function () {
|
||||
var S4 = function () {
|
||||
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
|
||||
}
|
||||
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
|
||||
},
|
||||
|
||||
// a classic iterator
|
||||
each: function (callback) {
|
||||
var cb = this.lambda(callback)
|
||||
// iterate from chain
|
||||
if (this.__results) {
|
||||
for (var i = 0, l = this.__results.length; i < l; i++) cb.call(this, this.__results[i], i)
|
||||
}
|
||||
// otherwise iterate the entire collection
|
||||
else {
|
||||
this.all(function(r) {
|
||||
for (var i = 0, l = r.length; i < l; i++) cb.call(this, r[i], i)
|
||||
})
|
||||
}
|
||||
return this
|
||||
}
|
||||
// --
|
||||
};
|
225
DroidGap/lawnchair-adapter-test/www/lib/qunit.css
Normal file
225
DroidGap/lawnchair-adapter-test/www/lib/qunit.css
Normal file
@ -0,0 +1,225 @@
|
||||
/**
|
||||
* QUnit - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://docs.jquery.com/QUnit
|
||||
*
|
||||
* Copyright (c) 2011 John Resig, Jörn Zaefferer
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* or GPL (GPL-LICENSE.txt) licenses.
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header */
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 15px 15px 0 0;
|
||||
-moz-border-radius: 15px 15px 0 0;
|
||||
-webkit-border-top-right-radius: 15px;
|
||||
-webkit-border-top-left-radius: 15px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2b81af;
|
||||
color: #fff;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #fff;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #c2ccd1;
|
||||
text-decoration: none;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests ol {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
-webkit-border-radius: 15px;
|
||||
|
||||
box-shadow: inset 0px 2px 13px #999;
|
||||
-moz-box-shadow: inset 0px 2px 13px #999;
|
||||
-webkit-box-shadow: inset 0px 2px 13px #999;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
margin: 0.5em;
|
||||
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #5E740B;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #EE5757;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 15px 15px;
|
||||
-moz-border-radius: 0 0 15px 15px;
|
||||
-webkit-border-bottom-right-radius: 15px;
|
||||
-webkit-border-bottom-left-radius: 15px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: green; }
|
||||
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Result */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
color: #2b81af;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
}
|
1448
DroidGap/lawnchair-adapter-test/www/lib/qunit.js
Normal file
1448
DroidGap/lawnchair-adapter-test/www/lib/qunit.js
Normal file
File diff suppressed because it is too large
Load Diff
96
DroidGap/lawnchair-adapter-test/www/master.css
Normal file
96
DroidGap/lawnchair-adapter-test/www/master.css
Normal file
@ -0,0 +1,96 @@
|
||||
body {
|
||||
background:#222 none repeat scroll 0 0;
|
||||
color:#666;
|
||||
font-family:Helvetica;
|
||||
font-size:72%;
|
||||
line-height:1.5em;
|
||||
margin:0;
|
||||
border-top:1px solid #393939;
|
||||
}
|
||||
|
||||
#info{
|
||||
background:#ffa;
|
||||
border: 1px solid #ffd324;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
clear:both;
|
||||
margin:15px 6px 0;
|
||||
width:295px;
|
||||
padding:4px 0px 2px 10px;
|
||||
}
|
||||
|
||||
#info > h4{
|
||||
font-size:.95em;
|
||||
margin:5px 0;
|
||||
}
|
||||
|
||||
#stage.theme{
|
||||
padding-top:3px;
|
||||
}
|
||||
|
||||
/* Definition List */
|
||||
#stage.theme > dl{
|
||||
padding-top:10px;
|
||||
clear:both;
|
||||
margin:0;
|
||||
list-style-type:none;
|
||||
padding-left:10px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#stage.theme > dl > dt{
|
||||
font-weight:bold;
|
||||
float:left;
|
||||
margin-left:5px;
|
||||
}
|
||||
|
||||
#stage.theme > dl > dd{
|
||||
width:45px;
|
||||
float:left;
|
||||
color:#a87;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
/* Content Styling */
|
||||
#stage.theme > h1, #stage.theme > h2, #stage.theme > p{
|
||||
margin:1em 0 .5em 13px;
|
||||
}
|
||||
|
||||
#stage.theme > h1{
|
||||
color:#eee;
|
||||
font-size:1.6em;
|
||||
text-align:center;
|
||||
margin:0;
|
||||
margin-top:15px;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
#stage.theme > h2{
|
||||
clear:both;
|
||||
margin:0;
|
||||
padding:3px;
|
||||
font-size:1em;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
/* Stage Buttons */
|
||||
#stage.theme a.btn{
|
||||
border: 1px solid #555;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
text-align:center;
|
||||
display:block;
|
||||
float:left;
|
||||
background:#444;
|
||||
width:150px;
|
||||
color:#9ab;
|
||||
font-size:1.1em;
|
||||
text-decoration:none;
|
||||
padding:1.2em 0;
|
||||
margin:3px 0px 3px 5px;
|
||||
}
|
||||
#stage.theme a.btn.large{
|
||||
width:308px;
|
||||
padding:1.2em 0;
|
||||
}
|
||||
|
201
DroidGap/lawnchair-adapter-test/www/webkit-sqlite.js
Normal file
201
DroidGap/lawnchair-adapter-test/www/webkit-sqlite.js
Normal file
@ -0,0 +1,201 @@
|
||||
Lawnchair.adapter('webkit-sqlite', (function () {
|
||||
// private methods
|
||||
var fail = function (e, i) { console.log('error in sqlite adaptor!', e, i) }
|
||||
, now = function () { return new Date() } // FIXME need to use better date fn
|
||||
// not entirely sure if this is needed...
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function( obj ) {
|
||||
var slice = [].slice
|
||||
, args = slice.call(arguments, 1)
|
||||
, self = this
|
||||
, nop = function () {}
|
||||
, bound = function () {
|
||||
return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)))
|
||||
}
|
||||
nop.prototype = self.prototype
|
||||
bound.prototype = new nop()
|
||||
return bound
|
||||
}
|
||||
}
|
||||
|
||||
// public methods
|
||||
return {
|
||||
|
||||
//valid: function() { return !!(window.openDatabase) },
|
||||
valid: function() { return !!(window.my_openDatabase) },
|
||||
//valid: function() { return !!(sqlitePlugin.openDatabase) },
|
||||
|
||||
init: function (options, callback) {
|
||||
var that = this
|
||||
, cb = that.fn(that.name, callback)
|
||||
, create = "CREATE TABLE IF NOT EXISTS " + this.name + " (id NVARCHAR(32) UNIQUE PRIMARY KEY, value TEXT, timestamp REAL)"
|
||||
, win = function(){ return cb.call(that, that); }
|
||||
// open a connection and create the db if it doesn't exist
|
||||
//this.db = openDatabase(this.name, '1.0.0', this.name, 65536)
|
||||
//this.db = my_openDatabase(this.name, '1.0.0', this.name, 65536)
|
||||
this.db = window.my_openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
|
||||
//this.db = sqlitePlugin.openDatabase(this.name, '1.0.0', this.name, 65536)
|
||||
this.db.transaction(function (t) {
|
||||
t.executeSql(create, [], win, fail)
|
||||
})
|
||||
},
|
||||
|
||||
keys: function (callback) {
|
||||
var cb = this.lambda(callback)
|
||||
, that = this
|
||||
, keys = "SELECT id FROM " + this.name + " ORDER BY timestamp DESC"
|
||||
|
||||
this.db.transaction(function(t) {
|
||||
var win = function (xxx, results) {
|
||||
if (results.rows.length == 0 ) {
|
||||
cb.call(that, [])
|
||||
} else {
|
||||
var r = [];
|
||||
for (var i = 0, l = results.rows.length; i < l; i++) {
|
||||
r.push(results.rows.item(i).id);
|
||||
}
|
||||
cb.call(that, r)
|
||||
}
|
||||
}
|
||||
t.executeSql(keys, [], win, fail)
|
||||
})
|
||||
return this
|
||||
},
|
||||
// you think thats air you're breathing now?
|
||||
save: function (obj, callback) {
|
||||
var that = this
|
||||
, id = obj.key || that.uuid()
|
||||
, ins = "INSERT INTO " + this.name + " (value, timestamp, id) VALUES (?,?,?)"
|
||||
, up = "UPDATE " + this.name + " SET value=?, timestamp=? WHERE id=?"
|
||||
, win = function () { if (callback) { obj.key = id; that.lambda(callback).call(that, obj) }}
|
||||
, val = [now(), id]
|
||||
// existential
|
||||
that.exists(obj.key, function(exists) {
|
||||
// transactions are like condoms
|
||||
that.db.transaction(function(t) {
|
||||
// TODO move timestamp to a plugin
|
||||
var insert = function (obj) {
|
||||
val.unshift(JSON.stringify(obj))
|
||||
t.executeSql(ins, val, win, fail)
|
||||
}
|
||||
// TODO move timestamp to a plugin
|
||||
var update = function (obj) {
|
||||
delete(obj.key)
|
||||
val.unshift(JSON.stringify(obj))
|
||||
t.executeSql(up, val, win, fail)
|
||||
}
|
||||
// pretty
|
||||
exists ? update(obj) : insert(obj)
|
||||
})
|
||||
});
|
||||
return this
|
||||
},
|
||||
|
||||
// FIXME this should be a batch insert / just getting the test to pass...
|
||||
batch: function (objs, cb) {
|
||||
|
||||
var results = []
|
||||
, done = false
|
||||
, that = this
|
||||
|
||||
var updateProgress = function(obj) {
|
||||
results.push(obj)
|
||||
done = results.length === objs.length
|
||||
}
|
||||
|
||||
var checkProgress = setInterval(function() {
|
||||
if (done) {
|
||||
if (cb) that.lambda(cb).call(that, results)
|
||||
clearInterval(checkProgress)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
for (var i = 0, l = objs.length; i < l; i++)
|
||||
this.save(objs[i], updateProgress)
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
get: function (keyOrArray, cb) {
|
||||
var that = this
|
||||
, sql = ''
|
||||
// batch selects support
|
||||
if (this.isArray(keyOrArray)) {
|
||||
sql = 'SELECT id, value FROM ' + this.name + " WHERE id IN ('" + keyOrArray.join("','") + "')"
|
||||
} else {
|
||||
sql = 'SELECT id, value FROM ' + this.name + " WHERE id = '" + keyOrArray + "'"
|
||||
}
|
||||
// FIXME
|
||||
// will always loop the results but cleans it up if not a batch return at the end..
|
||||
// in other words, this could be faster
|
||||
var win = function (xxx, results) {
|
||||
var o = null
|
||||
, r = []
|
||||
if (results.rows.length) {
|
||||
for (var i = 0, l = results.rows.length; i < l; i++) {
|
||||
o = JSON.parse(results.rows.item(i).value)
|
||||
o.key = results.rows.item(i).id
|
||||
r.push(o)
|
||||
}
|
||||
}
|
||||
if (!that.isArray(keyOrArray)) r = r.length ? r[0] : null
|
||||
if (cb) that.lambda(cb).call(that, r)
|
||||
}
|
||||
this.db.transaction(function(t){ t.executeSql(sql, [], win, fail) })
|
||||
return this
|
||||
},
|
||||
|
||||
exists: function (key, cb) {
|
||||
var is = "SELECT * FROM " + this.name + " WHERE id = ?"
|
||||
, that = this
|
||||
, win = function(xxx, results) { if (cb) that.fn('exists', cb).call(that, (results.rows.length > 0)) }
|
||||
this.db.transaction(function(t){ t.executeSql(is, [key], win, fail) })
|
||||
return this
|
||||
},
|
||||
|
||||
all: function (callback) {
|
||||
var that = this
|
||||
, all = "SELECT * FROM " + this.name
|
||||
, r = []
|
||||
, cb = this.fn(this.name, callback) || undefined
|
||||
, win = function (xxx, results) {
|
||||
if (results.rows.length != 0) {
|
||||
for (var i = 0, l = results.rows.length; i < l; i++) {
|
||||
var obj = JSON.parse(results.rows.item(i).value)
|
||||
obj.key = results.rows.item(i).id
|
||||
r.push(obj)
|
||||
}
|
||||
}
|
||||
if (cb) cb.call(that, r)
|
||||
}
|
||||
|
||||
this.db.transaction(function (t) {
|
||||
t.executeSql(all, [], win, fail)
|
||||
})
|
||||
return this
|
||||
},
|
||||
|
||||
remove: function (keyOrObj, cb) {
|
||||
var that = this
|
||||
, key = typeof keyOrObj === 'string' ? keyOrObj : keyOrObj.key
|
||||
, del = "DELETE FROM " + this.name + " WHERE id = ?"
|
||||
, win = function () { if (cb) that.lambda(cb).call(that) }
|
||||
|
||||
this.db.transaction( function (t) {
|
||||
t.executeSql(del, [key], win, fail);
|
||||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
nuke: function (cb) {
|
||||
var nuke = "DELETE FROM " + this.name
|
||||
, that = this
|
||||
, win = cb ? function() { that.lambda(cb).call(that) } : function(){}
|
||||
this.db.transaction(function (t) {
|
||||
t.executeSql(nuke, [], win, fail)
|
||||
})
|
||||
return this
|
||||
}
|
||||
//////
|
||||
}})())
|
@ -230,6 +230,8 @@ Legacy PhoneGap (old version)
|
||||
Lawnchair Adapter Usage
|
||||
=======================
|
||||
|
||||
**NOTE:** For the Android version see DroidGap/lawnchair-adapter-test, which is using a Lawnchair adapter based on the original WebKit version. The plan is to make this one work for both iOS and Android versions.
|
||||
|
||||
Include the following js files in your html:
|
||||
|
||||
- lawnchair.js (you provide)
|
||||
|
Loading…
Reference in New Issue
Block a user