mirror of
https://github.com/moparisthebest/PhoneGap-SQLitePlugin-Android
synced 2024-11-29 03:42:15 -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
|
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:
|
Include the following js files in your html:
|
||||||
|
|
||||||
- lawnchair.js (you provide)
|
- lawnchair.js (you provide)
|
||||||
|
Loading…
Reference in New Issue
Block a user