Phonegap- insert data in online and show it in offline using database - javascript

i want to insert data in database when the device is online ,if the device is offline i want to show the data which is stored in database.
currently here i parse the data from rss feed and insert the data in database when the device is online and i cannot show the same data when the device is become offline.And also i tried lot of times to show the data in offline,using the following code:
document.addEventListener("offline", yourCallbackFunction, false);
$.each(data.responseData.feed.entries, function (e, item) {
var titles=item.title;
var linked=item.link;
s += '<li><div class="itemTitle"><a href="' + item.link + '" target="' + def.TitleLinkTarget + '" >' + item.title + "</a></div>";
if (def.ShowPubDate) {
i = new Date(item.publishedDate);
s += '<div class="itemDate">' + i.toLocaleDateString() + "</div>";
}
if (def.ShowDesc) {
if (def.DescCharacterLimit > 0 && item.content.length > def.DescCharacterLimit) {
s += '<div class="itemContent">' + item.content.substr(0, def.DescCharacterLimit) + "...</div>";
}
else {
s += '<div class="itemContent">' + item.content + "</div>";
console.log(s);
}
}
// Wait for PhoneGap to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// Populate the database
//
function populateDB(tx) {
tx.executeSql('DROP TABLE IF EXISTS DEMO');
tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (title, desc)');
tx.executeSql('INSERT INTO DEMO (title, desc) Values(?,?)',[titles,s]);
}
// Query the database
//
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
// Query the success callback
//
function querySuccess(tx, results) {
var len = results.rows.length;
console.log("DEMO table: " + len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " + results.rows.item(i).title + " Data = " + results.rows.item(i).desc);
$("#apps ul").append('<li><span class="tab">' +results.rows.item(i).desc+'</span></li>');
}
}
document.addEventListener("offline", querySuccess, false);

did you fire the event from the "ondeviceready" callback? i ask because this is a common mistake, but you need show us your code if you want anyone to be able to see whats wrong.
anyway, you can alaways use the navigator.connection.type property, and if you feel like reinventing the wheel you can bind your callback function to an event fired when connection.type is none. for more details:
http://docs.phonegap.com/en/2.9.0/cordova_connection_connection.md.html#Connection
also:
did you check if the data actually stored on you local db?
try to see exactly where the problem is before asking for arbitrary help.

as i thought, added the offline event listener before the device was ready, meaning before the functnionality needed to add event listener was loaded from your phonegap file. the correct way to write it is:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){
document.addEventListener("offline", querySuccess, false);
}

Related

Trying to execute code on device ready

I am trying to execute some Javascript code on deviceready by using a listener.
It doesn't seem to be calling the code - I'm getting nothing in my console, and none of the variables are set.
This is the code example I'm using:
<script>
// Cordova is ready
function onDeviceReady() {
var db = window.sqlitePlugin.openDatabase({name: "my.db"});
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)');
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("res.rows.length: " + res.rows.length + " -- should be 1");
console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
}, function(e) {
console.log("ERROR: " + e.message);
});
});
}
// Wait for Cordova to load
document.addEventListener("deviceready", onDeviceReady, false);
</script>
Now, I'm not primarily a Javascript developer (so this question may be simple), but is there some reason why the code is not executing? Do I have to run it in an anonymous function?
How do I get the onDeviceReady() function to execute?
deviceready is a special Cordova event; unless you launch your code in a Cordova environment, the event will never get fired (and your code will never get executed).
You can run Cordova in the browser by adding the browser as a platform. For more info, see http://www.raymondcamden.com/2014/09/24/Browser-as-a-platform-for-your-PhoneGapCordova-apps.
You could also use something like Ripple to emulate the Cordova environment in Chrome.
Since Cordova-SQLitePlugin API is asynchronous, you should execute transaction after the db is available/created. Try to implement it in a similar way as below:
var openDb = function (name, ok, error) {
try {
// SQLitePlugin always uses callbacks to specify the status of 'open' operation
var dbRef = window.sqlitePlugin.openDatabase({name: name},
function (db) {
log("DataBase " + name + " opened!");
ok(db);
}, function (e) {
try {
dbRef.close();
} catch (e) {
log("Could not close database", e);
}
error(e);
});
} catch (e) {
log("Could not open " + name + " DataBase");
error(e);
}
};
openDb("my.db", function(db){
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)');
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("res.rows.length: " + res.rows.length + " -- should be 1");
console.log("res.rows.item(0).cnt: " + res.rows.item(0).cnt + " -- should be 1");
});
}, function(e) {
console.log("ERROR: " + e.message);
});
});
});

Converting an MVC4 Web API Application to Phonegap Android Application

I have an MVC4 Web API application where i have my Api Controller and Code-First EF5 database and some JavaScript functions for the functionality of my app including my Ajax Calls for my Web Api Service.I did the project on MVC because i was having trouble installing Cordova in VS2012, so i have decided to use Eclipse/Android Phonegap platform.Is there a way where i can call my web api service and be able to retrieve my database data designed EF5(MVC4) in my Android Phonegap application without having to start from the beginning the same thing again.I know phonegap is basically Html(JavaScript and Css) but i am having trouble calling my service using the same HTML markup that i used MVC4.I am a beginner please let me know if what i am doing is possible and if not please do show me the light of how i can go about this. T*his is my Html code*
<script type="text/javascript" charset="utf-8" src="phonegap-2.9.0.js"></script>
<script type="text/javascript" charset="utf-8" src="barcodescanner.js"></script>
<script type="text/javascript" language="javascript" src="http://api.afrigis.co.za/loadjsapi/?key=...&version=2.6">
</script>
<script type="text/javascript" language="javascript">
// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);
//initialize watchID Variable
var watchID = null;
// device APIs are available
function onDeviceReady() {
// Throw an error if no update is received every 30 seconds
var options = { timeout: 30000 };
watchID = navigator.geolocation.watchPosition(onSuccess, onError, options);
// onSuccess Geolocation
//
function onSuccess(position) {
var element = document.getElementById('geolocation');
element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' +
'Longitude: ' + position.coords.longitude + '<br />' +
'<hr />' + element.innerHTML;
}
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
}
//declare a global map object
var agmap = null;
// declare zoom control of map
var zoomCtrl = null;
function initAGMap() {
agmap = new AGMap(document.getElementById("MapPanel"));
//TODO: must retrieve coords by device location not hard corded.
agmap.centreAndScale(new AGCoord(-25.7482681540537, 28.225935184269), 5); // zoom level 5 heres
// making zoom controls for map
var ctrlPos = new AGControlPosition(new AGPoint(10, 10), AGAnchor.TOP_LEFT);
zoomCtrl = new AGZoomControl(1);
agmap.addControl(zoomCtrl, ctrlPos);
}
function removeZoomCtrl()
{
zoomCtrl.remove();
}
//function search() {
// var lat = $('#latitude').val();
// var long = $('#longitude').val();
// $.ajax({
// url: "api/Attractions/?longitude=" + long + "&latitude=" + lat,
// type: "GET",
// success: function (data) {
// if (data == null) {
// $('#attractionName').html("No attractions to search");
// }
// else {
// $('#attractionName').html("You should visit " + data.Name);
// displayMap(data.Location.Geography.WellKnownText, data.Name);
// }
// }
// });
//}
//function GetCoordinate() {
//todo: get details from cordova, currently mocking up results
//return { latitude: -25.5, longitude: 28.5 };
}
function ShowCoordinate(coords) {
agmap.centreAndScale(new AGCoord(coords.latitude, coords.longitude), 5); // zoom level 5 here
var coord = new AGCoord(coords.latitude, coords.longitude);
var oMarker = new AGMarker(coord);
agmap.addOverlay(oMarker);
oMarker.show();
//todo: create a list of places found and display with marker on AfriGIS Map.
}
function ScanProduct()
{
//todo retrieve id from cordova as mockup
//This is mockup barcode
//return "1234";
//sample code using cordova barcodescanner plugin
var scanner = cordova.require("cordova/plugin/BarcodeScanner");
scanner.scan(
function (result) {
alert("We got a barcode\n" +
"Result: " + result.text + "\n" +
"Format: " + result.format + "\n" +
"Cancelled: " + result.cancelled);
},
//Callback function if barcodedont exist
function (error) {
alert("Scanning failed: " + error);
});
}
//Function to display Success or error in encoding.
function encode(type, data) {
window.plugins.barcodeScanner.encode(type, data, function(result) {
alert("encode success: " + result);
}, function(error) {
alert("encoding failed: " + error);
});}
function GetProductDetails(barcodeId,coords)
{
//Ajax Call to my web Api service
$.getJSON("api/products/?barcodeId=" + barcodeId + "&latitude=" + coords.latitude + "&longitude=" + coords.longitude)
.done(function (data) {
$('#result').append(data.message)
console.log(data)
var list = $("#result").append('<ul></ul>').find('ul');
$.each(data.results, function (i, item)
{
if (data.results == null) {
$('#result').append(data.message)
}
else {
list.append('<li>ShopName :' + item.retailerName + '</li>');
list.append('<li>Name : ' + item.productName + '</li>');
list.append('<li>Rand :' + item.price + '</li>');
list.append('<li>Distance in Km :' + item.Distance + '</li>');
//Another Solution
//var ul = $("<ul></ul>")
//ul.append("<li> Rand" + data.results.productName + "</li>");
//ul.append("<li> Rand" + data.results.Retailer.Name + "</li>");
//ul.append("<li> Rand" + data.results.price + "</li>");
//ul.append("<li> Rand" + data.results.Distance + "</li>");
//$("#result").append(ul);
}
});
$("#result").append(ul);
});
}
function ShowProductDetails()
{
//todo: display product details
//return productdetails.barcodeId + productdetails.retailerName + ': R' + productdetails.Price + productdetails.Distance;
}
//loading javascript api
$(function () {
initAGMap();
var coord = GetCoordinate();
ShowCoordinate(coord);
var barcodeId = ScanProduct();
var productdetails = GetProductDetails(barcodeId, coord);
ShowProductDetails(productdetails);
});
</script>
It looks like you're on the right track. The obvious error right now is that it's using a relative URL (api/products/?barcodeId=) to call the Web API. Because the HTML is no longer hosted on the same server as the Web API (even though you might be running them both on your local machine still), this won't work anymore. You need to call the service with an absolute URL (for example, http://localhost:8888/api/products/?barcodeId=).
Where is your Web API hosted right now and how are you running the Cordova code? If the Web API is up and running on your local machine and your Cordova app is running on an emulator on the same machine, you should be able to call the service by supplying its full localhost path.
If it still doesn't work, you'll need to somehow debug the code and see what the errors are.

Cannot get json results from twitter using PhoneGap and jQuery

I'm trying to get the last 50 tweets using a certain hash tag, on a mobile device using PhoneGap (0.9.6) and jQuery (1.6.1). Here's my code:
function getTweets(hash, numOfResults) {
var uri = "http://search.twitter.com/search.json?q=" + escape(hash) + "&callback=?&rpp=" + numOfResults;
console.log("uri: " + uri);
$.getJSON(uri, function(data) {
var items = [];
if(data.results.length > 0) {
console.log("got " + data.results.length + " results");
$.each(data.results, function(key, val) {
var item = "<li>";
item += "<img width='48px' height='48px' src='" + val.profile_image_url + "' />";
item += "<div class='tweet'><span class='author'>" + val.from_user + "</span>";
item += "<span class='tweettext'>" + val.text + "</span>";
item += "</div>";
item += "</li>";
items.push(item);
});
}
else {
console.log("no results found for " + hash);
items.push("<li>No Tweets about " + hash + " yet</li>");
}
$("#tweetresults").html($('<ul />', {html: items.join('')}));
});
}
This code works great in a browser, and for a while worked in the iPhone simulator. Now it's not working on either the iPhone or Android simulator. I do not see any of the console logs and it still works in a browser.
What am I doing wrong? If it's not possible to call getJson() on a mobile device using PhoneGap, what is my alternative (hopefully without resorting to native code - that would beat the purpose).
Bonus: how can I debug this on a mobile simulator? In a browser I use the dev tools or Firebug, but in the simulators, as mentioned, I don't even get the log messages.
As always, thanks for your time,
Guy
Update:
As #Greg intuited, the function wasn't called at all. Here's what I found and how I bypassed it:
I have this <a> element in the HTML Get tweets
Then I have this code in the $(document).ready() function:
$("#getTweets").click(function() {
var hash = "#bla";
getTweets(hash, 50);
});
That didn't call the function. But once I changed the code to:
function gt() {
var hash = "#bla";
getTweets(hash, 50);
}
and my HTML to:
Get Tweets
it now works and calls Twitter as intended. I have no idea what's screwed up with that particular click() binding, but I ran into similar issues with PhoneGap before. Any ideas are appreciated.
Considering that (a) there isn't much that could go wrong with the first line of your function and (b) the second line is a log command, then it would seem that the function isn't being called at all. You'll have to investigate the other code in your app.
Or are you saying that you don't have a way to read logged messages on your mobile devices?

Things are happening outside my for loop before its done (javascript)

I'm sure I've seen this before and know the answer to it but after 12 hours... my mind is complete mush.
I have a for loop in which I am trying to concatenate onto a string so that AFTER I can complete the string (thus completing a nice little table) that I had hoped to then insert into my html and show the user.
However, the things at the end of my function (after my for loop) are getting called before the for loop ever does....
function getEntries() {
$('#entryTotalsDiv').html('<img src="images/ajax-loader.gif" /> ... retrieving form totals.');
var entryTotalsTable = "<table id='entryTable' class='display' style='border:1px;'><thead><tr><th>Form Name</th><th>Hash</th><th>Entries</th></tr></thead>" +
"<tbody>"
//Get rows ONE at a time.
var countNumber = 1;
for (var frm = 0; frm < numberOfForms; frm++) {
$.post('ajax/getEntries.aspx',
{
'formNumber': frm
},
function (data) {
entryTotalsTable += "<tr><td>" + data[0].formName + "</td><td>" + data[0].formHash + "</td><td>" + data[0].formEntryCount + "</td></tr>";
//Now go and update the Form Retrieval div -- add 1 to the frm Number
$('#formNamesDiv').html(countNumber + ' of ' + numberOfForms + ' retrieved.');
countNumber++;
});
}
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
If you notice, I wanted to close up the Table html at the end, but this gets called before my for loop is finished, thus screwing up my string...
?
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
A solution could be to save every response in an array and test in every callback whether the current count is equal to the total count. Something like:
var countNumber = 1,
allData = [];
function runWhenFinished() {
if(countNumber === numberOfForms) {
var entryTotalsTable = "<table id='entryTable' class='display' style='border:1px;'><thead><tr><th>Form Name</th><th>Hash</th><th>Entries</th></tr></thead>" + "<tbody>";
for(var i = 0, l = allData.length; i < l; i++) {
entryTotalsTable += "<tr><td>" + allData[i].formName + "</td><td>" + allData[i].formHash + "</td><td>" + allData[i].formEntryCount + "</td></tr>";
}
entryTotalsTable += "</tbody></table>";
$('#entriesDiv').html(entryTotalsTable);
//Now bind the table to the DataTables JQ script
$('#entryTable').dataTable();
$('#entryTable').show('slow');
}
}
for(var frm = 0; frm < numberOfForms; frm++) {
(function(frm) {
$.post('ajax/getEntries.aspx',{'formNumber': frm}, function (data) {
allData[frm] = data[0];
countNumber++;
$('#formNamesDiv').html(countNumber + ' of ' + numberOfForms + ' retrieved.');
runWhenFinished();
});
}(frm));
}
I'm sure this can still be improved, but you get the idea.
If you really make 70 requests then you might want to rethink your strategy anyway. 70 simultaneous requests is a lot.
E.g. you could make one request and prove the minimum and maximum number of that should be retrieved / updated / whatever the method is doing.
$.post is asynchronous, meaning that it's firing off all the requests in the loop as fast as it can, and then exiting the loop. It doesn't wait for a response. When the response comes back, your row function is then called... but by then, all the posts have been sent on their way.
See the answers to this question here...
How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
You'll need to change from $.post to $.ajax

Phonegap-Android-sqlite using Javascript. How to connect?

I am new to Android-Phonegap dev. I am creating a project using Eclipse in Windows XP.
I am using sqlite database. I saw the sample code in the docs. But I'm not able to execute this example. I am not getting the required results.
Suppose I want to get all the entries in the table demo in tabular format, HTML. What will the code be in index.html? For that, what is the procedure and what is the step by step procedure for doing this? Or else any better tutorials which help me to do this?
Thanks in Advance
Dnyan.
in main.js you add this
rowsDataHandler = function(transaction, results) {
// Handle the results
var html = "<ul>";
for (var i=0; i<results.rows.length; i++) {
var row = results.rows.item(i);
html += '<li>'+row['data']+'</li>\n';
}
html +='</ul>';
document.getElementById("mydata").innerHTML = html;
}
// load the currently selected icons
loadRows = function(db) {
try {
db.executeSql('SELECT * FROM DEMO',[], rowsDataHandler, errorCB);
} catch(e) {alert(e.message);}
}
in index.html you add this row inside body
<div id="mydata"></div>
One thing to bear in mind is that if you aren't testing the application on a device or in an emulator, but rather in a browser like Chrome or Safari,
document.addEventListener("deviceready", onDeviceReady, false);
won't work. What I've done is to comment out this line and just to put in a call to
onDeviceReady();
When I then test in the emulator I uncomment the "document…" line and comment out
onDeviceReady();
**html**
<input id="show" type="button" value="Show">
**js**
function globalError(tx, error)
{
alert("Error: " + error.message);
}
var db = window.openDatabase('TabOrder', '', 'Bar Tab Orders', 2500000);
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS SubmiteData;', null, null, globalError);
tx.executeSql('CREATE TABLE IF NOT EXISTS SubmiteData (SubmiteDataId integer
primary key, UserId text, AuthNo number, LocId number,ProdId number,
CardId number, OrgLat text, OrgLng text, OrgTime text)',
null,
function()
{
SubmiteData("USER1",12345678,23434, 21212, 220232,
"9", "45", "23/06/2014");
},
globalError);
});
function SubmiteData(UserId, AuthNo, LocId,ProdId, CardId, OrgLat, OrgLng, OrgTime){
db.transaction(function(tx){
tx.executeSql('INSERT INTO SubmiteData(UserId, AuthNo, LocId, ProdId, CardId,
OrgLat, OrgLng, OrgTime) VALUES (?,?,?,?,?,?,?,?)', [UserId, AuthNo, LocId,
ProdId, CardId, OrgLat, OrgLng, OrgTime],
null,
globalError
);
});
}
function read(UserId, AuthNo, LocId,ProdId, CardId, OrgLat, OrgLng, OrgTime){
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM SubmiteData',
[],
function(tx, results)
{
for (var i=0; i<results.rows.length; i++)
{
var row=results.rows.item(i);
// alert("Id: " + row['UserId']);
var stringout = "LocId: " + row['LocId'] + "\n";
alert(stringout);
}
},
globalError
);
});
};
$(function()
{
$('#show').click(read);
});
this is the method to connect to a db using javascript
db = openDatabase("bprueba","1.0","Prueba_db",5*1023*1024);
SQL Statement Error Callback Reference

Categories

Resources