Quantcast
Channel: iPhone Dev Log » Web storage
Viewing all articles
Browse latest Browse all 2

Cordova-supported WebSQL Database, with user-added data

$
0
0

In this article, we are examining another facet of the database storage, which is built into Cordova. In this article, we’ll create an empty database and allow the user to add records to the database and store them in the device. A button will delete the database. Two outputs are given, one in a text field and one in a table layout. With the text-only layout in the textfield, you can press and hold in the textfield and copy the contents to export it.

The code here on this page creates all the database entries on an HTML page, not from a server. It is not a pre-populated database. Uploading a new version of the app retained the old database structure and all its data.

The table made here has four fields, id, which is created according to the time to keep it unique, and data1, data2, and data3. The user-entered data is placed into localStorage early, then pulled from localStorage several functions later when it’s time to insert it into the database.

To get started, set up a project as noted in http://iphonedevlog.wordpress.com/2014/01/31/adding-cordova-apis-to-android-via-cli-accelerometer-and-camera/ You’ll want to follow the “Set Up the Android Project” section through step 9 inclusive. Start a new page in the project and call it storage-insert.html. Copy/paste from this page into that page. I’ve commented out the processes from beginning to end. Link to it as a button from your original index.html page if you wish. What you see below is the complete code.

No other pages are required. No server is used. You can even double-click on the file on your hard drive and test-drive it in a browser like Google Chrome. There are no plugins to download, nor editing of config.xml. Cordova.js isn’t needed. This database, which conforms closely to WebSQL, has a 5MB data limit. For more details, see http://dev.w3.org/html5/webdatabase/

My environment:

Mac OS X 10.9.1 on Mac Mini
Cordova CLI 3.4.0
for Android 4.3, 4.4 v19
ADT v22.0.1 with Eclipse platform (not using Eclipse at this time)
Testing in device: Android-19, Nexus 7 with 4.3 (cordova prepare/cordova compile)
Not for PG Build; no Jquery or other JS or CSS packages used

<!-- ********************* HMTL5 Storage begin *********************** -->
<!DOCTYPE html>
<html>
<head>
<title>User-generated DB (PG Storage Example)</title>
<meta name="viewport" content="width=device-width, initial-scale = 1.0, user-scalable = no">
<!-- <script type="text/javascript" charset="utf-8" src="cordova.js"></script> -->
<script type="text/javascript" charset="utf-8">

function onDeviceReady() { 
 persistData(data1, data2, data3);
}
</script>
<style type="text/css">
.buttonClass, h2, p, .inputClass, #output, td {
 font-family: "Helvetica"; color: #000; font-size:1em; 
}
h2 {
 font-size:1.3em; font-weight: bold;
}
.buttonClass, .inputClass, #output, .buttonDel {
 border-radius:8px; 
 border:#878787 solid 1px; padding:.5em 1em;margin:.5em;
 -webkit-appearance:none;
} 
.buttonClass, .inputClass, #output {
 width: 46%;
} 
.buttonDel {
 background-color: #faa;
}
.buttonClass {
 text-align: center; height: 3em; background-color:#fff;
}
.inputClass {
 text-align: left; height: 2em; background-color:#ffe; width:90%; 
} 
#output {
 text-align: left; height: auto; background-color:#ffe; width:90%; 
}
.segment {
 display:block; border-radius:8px; background-color:#eee;
 border:#878787 solid 1px; padding:1em; margin:.5em;
 -webkit-appearance:none; 
 height: auto; 
}
table {
 width:100%;
}
td {
 font-size:.8em;
 padding: .5em;
 width:25%;
 border:1px gray solid;
 overflow:auto;
 line-height:1em; 
 border-radius: 4px;
 background-color: #fff;
}
.headercell {
 text-align:center;
 font-weight:bold;
}
@media screen and (max-width:800px) {
 .buttonClass { width: 100%;}
}
</style>
</head>
<body>
<div class="segment">
 <h2>Storage, user-entry DB</h2>
 <input type="button" class="buttonClass" onclick='window.location="index.html"' value="Return">

 <form id="userInput" action ="" method="GET"> 
 <input class="inputClass" id="data1" type="text" value="" placeholder="data1"> 
 <input class="inputClass" id="data2" type="text" value="" placeholder="data2"> 
 <input class="inputClass" id="data3" type="text" value="" placeholder="data3"> 
 <br><br>
 <input class="buttonClass" type="button" value="Insert Data" onclick="persistData(this.form)">
 </form>

 <p><em>Press and hold on the text to copy and export. To scroll contents, tap in field and wait for keyboard, then scroll.</em></p>

<!-- insert query results here, text-only -->
 <textarea id="output" rows="15" placeholder="Results displayed here"></textarea> 

 <input type="button" class="buttonClass" style="background-color: #faa;" onclick='dropDb();' value="Delete Database">

<!-- insert query results here as table rows --> 
 <table><th><tr><td class="headercell">ID</td><td class="headercell">data1</td><td class="headercell">data2</td><td class="headercell">data3</td></tr></th></table>
 <div id="output2"></div>

 <input type="button" class="buttonClass" onclick='window.location="http://iphonedevlog.wordpress.com/2014/03/21/cordova-websql-database-with-user-added-data/"' value="View Code on iPhoneDevLog">
</div>

<script>

/* IMPORTANT! for increased security, add form validation (not used on this page). 
Perhaps get it from: http://rickharrison.github.io/validate.js/ */

// set form field input

function persistData(data1, data2, data3) {
// get form entries
 var form = document.getElementById("userInput"); 
 var formdata1 = form.data1.value;
 var formdata2 = form.data2.value;
 var formdata3 = form.data3.value;
// set value if input was blank
 if (formdata1 === "undefined") { formdata1 = "" }; 
 if (formdata2 === "undefined") { formdata2 = "" };
 if (formdata3 === "undefined") { formdata3 = "" };
// check form entries on console
 console.log("data1 = " + formdata1); 
 console.log("data2 = " + formdata2);
 console.log("data3 = " + formdata3);
// key, value pair into localStorage
 localStorage.setItem('formdata1Set', formdata1); 
 localStorage.setItem('formdata2Set', formdata2); 
 localStorage.setItem('formdata3Set', formdata3);
// set the current time as the id to make it unique id
 var d = new Date();
 var new_id = d.getTime();
 localStorage.setItem('new_idSet', new_id);
// proceed to next function
 startDB(); 
}

function startDB() {
 var db = window.openDatabase("Database", "1.0", "DEMO", 2000000);
 db.transaction(populateDB, errorCB, successCB);
}

// Form the query

function populateDB(tx) {
 var formdata1Get = localStorage.getItem('formdata1Set'); // get data from localStorage
 var formdata2Get = localStorage.getItem('formdata2Set');
 var formdata3Get = localStorage.getItem('formdata3Set');
 var new_idGet = localStorage.getItem('new_idSet');
// if no data has been entered, show note and stop the process
 if (formdata1Get.length < 1 && formdata2Get.length < 1 && formdata3Get.length < 1) { 
 document.getElementById("output").innerHTML = "\nPLEASE ENTER DATA"; return false; 
 }
 tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id TEXT NOT NULL, data1 TEXT NULL, data2 TEXT NULL, data3 TEXT NULL)'); 
 tx.executeSql('INSERT INTO DEMO (id, data1, data2, data3) VALUES (\"' + new_idGet + '\"' + ', \"' + formdata1Get + '\", \"' + formdata2Get + '\", \"' + formdata3Get + '\")');
 queryDB(tx);
}

// Execute the query, grabbing all the data

function queryDB(tx) {
 tx.executeSql("SELECT * FROM DEMO", [], querySuccess, errorCB);
}

function querySuccess(tx, results) {
 var len = results.rows.length;
 console.log("Returned rows = " + results.rows.length);
// set output, output2 to blank so values are not appended to previous values
 document.getElementById("output").innerHTML = "";
 document.getElementById("output2").innerHTML = "";
// loop through rows as many times as there are row results
 for (var i = 0; i < len; i++) { 
 var rowid = results.rows.item(i).id;
// Display the query results within <textarea id="output"></textarea>
 document.getElementById("output").innerHTML += "\nID = " + results.rows.item(i).id +
 "\ndata1 = " + results.rows.item(i).data1 +
 "\ndata2 = " + results.rows.item(i).data2 +
 "\ndata3 = " + results.rows.item(i).data3 + "\n";
 
// Display the query results as a table within <div id="output2"></div>
 document.getElementById("output2").innerHTML += "<table><tr><td><button class='buttonDel' onclick='delRecord(\"" + rowid + "\")' value='Delete'>Delete</button><br>" + results.rows.item(i).id + "</td><td>" + results.rows.item(i).data1 + "</td><td>" + results.rows.item(i).data2 + "</td><td>" + results.rows.item(i).data3 + "</td></tr></table>";
 console.log("rowid = " + rowid); 
 }
// reset form input fields to blank
 var form = document.getElementById("userInput"); 
 form.data1.value = "";
 form.data2.value = "";
 form.data3.value = ""; 
}

// Show DB onload (next two functions)

function showDB(tx) {
 var db = window.openDatabase("Database", "1.0", "DEMO", 2000000);
 db.transaction(createDB, errorCB, successCB);
}
function createDB(tx) {
 tx.executeSql("SELECT * FROM DEMO", [], querySuccess, errorCB);
}

// Delete a row in the DB from button

function delRecord(rowid) {
 var db = window.openDatabase("Database", "1.0", "DEMO", 2000000);
 db.transaction(
 function (tx) {
 tx.executeSql("DELETE FROM demo WHERE id = ?", [rowid]);
 }
 ); 
 document.getElementById("output").innerHTML = "";
 document.getElementById("output2").innerHTML = "";
 location.reload(false); // refresh page to show changes
}

// Transaction success callback

function successCB() {
 console.log("_______ Success! _______");
}

// Transaction error callback

function errorCB(err) {
 if (err.code == "0") {
 console.log("0 - UNKNOWN_ERR: The transaction failed for reasons unrelated to the database itself and not covered by any other error code.");
 }
 if (err.code == "1") {
 console.log("1 - DATABASE_ERR: The statement failed for database reasons not covered by any other error code.");
 }
 if (err.code == "2") {
 console.log("2 - VERSION_ERR: The operation failed because the actual database version was not what it should be. For example, a statement found that the actual database version no longer matched the expected version of the Database or DatabaseSync object, or the Database.changeVersion() or DatabaseSync.changeVersion() methods were passed a version that doesn't match the actual database version.");
 }
 if (err.code == "3") {
 console.log("3 - TOO_LARGE_ERR: The statement failed because the data returned from the database was too large. The SQL 'LIMIT' modifier might be useful to reduce the size of the result set.");
 }
 if (err.code == "4") {
 console.log("4 - QUOTA_ERR: The statement failed because there was not enough remaining storage space, or the storage quota was reached and the user declined to give more space to the database.");
 }
 if (err.code == "5") {
 console.log("5 - SYNTAX_ERR: The statement failed because of a syntax error, or the number of arguments did not match the number of ? placeholders in the statement, or the statement tried to use a statement that is not allowed, such as BEGIN, COMMIT, or ROLLBACK, or the statement tried to use a verb that could modify the database but the transaction was read-only.");
 }
 if (err.code == "6") {
 console.log("6 - CONSTRAINT_ERR: An INSERT, UPDATE, or REPLACE statement failed due to a constraint failure. For example, because a row was being inserted and the value given for the primary key column duplicated the value of an existing row.");
 }
 if (err.code == "7") {
 console.log("7 - TIMEOUT_ERR: A lock for the transaction could not be obtained in a reasonable time.");
 }
}


// "drop (delete) database" sequence, next two functions

function dropDb() {
// erase localStorage
 window.localStorage.clear();
// erase form fields
 var form = document.getElementById("userInput"); 
 form.data1.value = "";
 form.data2.value = "";
 form.data3.value = "";
 document.getElementById("output").innerHTML = "";
 document.getElementById("output2").innerHTML = "";
// start the "drop database" sequence
 var db = window.openDatabase("Database", "1.0", "DEMO", 2000000);
 db.transaction(dropDatabase, errorCB, successCB);
}
function dropDatabase(tx) {
 tx.executeSql('DROP TABLE IF EXISTS DEMO');
 console.log("_______ Table Dropped! _______");
}

// Show the DB contents on page load
showDB(); 
</script>
</body>
</html>
<!-- ********************* HMTL5 Storage end *********************** -->

1. Prepare the files in the terminal:

cordova prepare android

2. Compile the apk file:

cordova compile android

3. Locate the apk file at platforms/android/bin/CordovaAPI-debug.apk and put it on your device. I updated to 3.4.0 and found the apk in platforms/android/ant-build/

4. When the page opens, tap the data fields and enter information. Tap on the Insert Data button to insert records into the table. Scroll down to see the data in the large field and in table format further down. Tap on the Delete button in a row to delete that row. Tap on the Delete Database button to remove all content from the database and fields.

Storage, user-entry DB, topStorage, user-entry DB, bottom

 


Filed under: Android, PhoneGap Tagged: Android, Cordova APIs, database, localStorage, Web storage

Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images