Twitter: raymondcamden


Address: Lafayette, LA, USA

Example of a Parse.com JavaScript application with offline support

09-14-2012 17,880 views Mobile, Development, jQuery, JavaScript, HTML5 36 Comments

This morning I got a seemingly innocent question from a reader:

Came across your blog post on Parse + PhoneGap and wanted to get your opinion on the following use-case for that combo...

I've been exploring the possibilities of an app that essentially has a web form (similar to the contact form you've got right here, actually) that would store the resulting data via Parse. The reason being...it would be important that the app would allow a form to submit, even if there wasn't an active Internet connection available.

So, just wanted your thoughts on whether I am looking in the right direction to accomplish this. Don't have much experience in the way of iOS apps, but have to start somewhere, right?

I replied to him with a basic outline:

  • When you submit the form, hit Parse if you are online, hit WebSQL if not.
  • When the application starts, see if you have data in WebSQL, and if you are online, push it to parse.

That seemed simple enough, but I figured I might as well build a real demo just to prove it can be done. This is what I came up with. It's got some issues (don't we all?) but it covers the basics. As always though I'm open to suggestions for how this could be done better.

I began by creating the layout for an application. Since the reader just mentioned a form, I built the entire application around one form. I decided to build a simple UFO Report Form. It has a field for the number of UFOs, your name, and the description. I didn't make use of any UI framework but instead directed my incredible design skills at the task.

Here's the HTML behind the form, just in case your curious:

Fancy, eh? Ok, now it's time to get into the code. I'm going to tackle this piece by piece, and it may get a bit confusing, but I'll post the entire file in one chunk at the end for your perusal.

Whether or not we are online, we need to set up the database. This is done via the WebSQL API. While this API is deprecated, it is fully supported in PhoneGap and works great in Chrome, the main browser I use for testing.

I'm not going to detail how this works as I've covered it before (Example of PhoneGap's Database Support), but even if this is brand new to you I think you can get the idea.

After the database is set up, our application needs to upload any existing data to Parse. We're going to skip that now though and look at the basic form handling aspects of the code.

I wrote a function to wrap my check for online/offline support. Why? I wrote this demo without actually building it as a PhoneGap application. It should work fine when converting into a mobile application, and at that point my wrapper function can be modified to use PhoneGap's API, but for my initial testing I just wanted to use the navigator.onLine property. Having a wrapper also let me easily add in a hack (see the commented out line) to test being offline.

If we are online, I need to initialize Parse support. I won't repeat what is already covered in the Parse JavaScript Guide. Instead, this is just an example of how I initialize Parse.com with my API keys and define an object type I'm calling SightingObject (as in UFO sighting).

Now let's look at the form handler. Remember, this needs to either save to Parse or to the database.

This code block is a bit large, so let's break it down. The first thing I do is grab the values from the form. As mentioned in the comments, it would probably make sense to do some basic validation. Screw validation - this is a demo. Next I do some basic UI stuff to let the user know that exciting things are happening in the background (although in theory, not as exciting as the UFO in front of them). Then we have the online/offline block. I've taken the Parse logic out into another function that I'll show in a moment. The other part of the conditional simply writes it out to the database. In both cases we run a function, resetForm, that handles resetting my UI.

Here is saveToParse. Notice how darn easy this is. Just in case it isn't obvious - this is all the code I need to store my data, permanently, in the cloud. It would only be easier if the Parse.com engineers fed me grapes and lime jello shots while I wrote the code.

Before we get into the synchronization aspect, here is resetForm. Again, it just handles updating the UI and letting the user know something happened with their important data.

I did some quick testing and confirmed it was working. I used Parse.com's online data browser first:

I then tested offline storage. Chrome makes it easy to check since it has a database viewer built in:

That's almost it. The final piece of the puzzle is handling uploading the database data. This turned out to be simple too. If we are online, we can run a SQL against the table. If anything exists, we upload it and remove it.

That's basically it. The biggest issue with this code is that it doesn't handle a change to your online/offline status, specifically, if you start the application offline, save some sightings, and then become online, it won't upload the old rows. That wouldn't be too hard to fix, but I was trying to keep it simple. At minimum, the next time you run the application it will upload those old records. For folks who want to see the entire code base, simply view the gist here: https://gist.github.com/3723074

I've also included a zip attached to this blog entry. (Note that the animated gif is courtesy of jQuery Mobile.)

Download attached file

36 Comments

  • jean-louis #
    Commented on 09-16-2012 at 5:52 PM
    HI,
    would you show us how to "simply" retrieve the list of ufo's names descript in an html list ?
    thanks !
    jl
  • Commented on 09-16-2012 at 8:45 PM
    Sure - actually - it is going to be more difficult to the UI aspect. This "app" has one form. In order to add a list, I'd need to add some form of navigation to it. The actual act of asking Parse for the stuff is much simpler than the UI.

    That being said - I wanted to work on this app a bit more anyway. This gives me an opportunity too. :)
  • Commented on 09-16-2012 at 9:06 PM
    Here is a quick example where I just wrote it as a separate HTML file:

    https://gist.github.com/3735178

    It makes use of the Query API - https://parse.com/docs/js_guide#queries
  • jean-louis #
    Commented on 09-17-2012 at 11:45 AM
    Great! Exactly what I was looking for !
    thanks, jl
  • mkhuda #
    Commented on 12-23-2012 at 11:56 PM
    Thanks raymond ! its great example !
    Actually, i want to parse data from Parse.com and then store it in a local database with onclick/submit button ! How to do it?

    and Thank you for the tutorial ! :)
  • Commented on 12-24-2012 at 10:19 AM
    Well, my entries on Parse tell you how to get the data. So all you need to know is how to store it. In PhoneGap, that would be with WebSQL, their database support, and I've done a number of entries on that. Shoot, this blog entry shows you how to store into the db when you are offline - it is the exact same code to just plain store it.
  • mkhuda #
    Commented on 12-24-2012 at 1:25 PM
    this is my code,

    https://gist.github.com/4370435

    after I pressed the query button, I get the query does not work well.
  • Commented on 12-24-2012 at 1:50 PM
    Your Parse.init line should only be run once, so you want to move that out.

    You say the query does not work well. What exactly does that mean? I need a firm error to help.
  • Commented on 12-24-2012 at 1:51 PM
    Another issue. You are trying to insert a report.body (title) property but report doesn't exist. result[i] is your current object. I believe you also want to use result[i].get("title") to get the property. Check the Parse.com API docs to be clear.
  • mkhuda #
    Commented on 12-24-2012 at 2:53 PM
    oke, this is my complete code !

    https://gist.github.com/4370619

    I have 4 rows in note Class. and i have successfully storing data from Parse to local SQL with 4 rows, But only one row data is store to local SQL.
  • Commented on 12-24-2012 at 9:52 PM
    Do you get any errors though? Have you tried using console.log to see where things fail?
  • mkhuda #
    Commented on 12-24-2012 at 10:07 PM
    i dont get an error, im using google chrome console..
    and the javascript code is running well.
  • Commented on 12-24-2012 at 10:56 PM
    I'd add a bunch of console.log messages. If you want, you can send me your code (with the real app ids, I won't share) and I'll run it here... Wednesday.
  • mkhuda #
    Commented on 12-24-2012 at 11:55 PM
    this is my project files:

    http://dl.dropbox.com/u/37749698/local.zip

    Thank you in advance for your help and your time
  • Commented on 12-26-2012 at 12:01 PM
    I just tested and it is entering data just fine. How are you testing? For me, I go into Chrome Dev Tools, Resources, Web SQL, I clicked on the db name, then click on the table name (maybe double click) and I see rows of data from the inserts.
  • mkhuda #
    Commented on 12-26-2012 at 4:59 PM
    I have 4 rows in Parse.com DB.
    this is my Parse rows:
    http://dl.dropbox.com/u/37749698/rows.jpg
    but why only the last row inserted into my local SQL ?
    [body: mk] [title: mkhuda] counted 4 times.
  • Commented on 12-27-2012 at 11:36 AM
    Ohh, yeah, this is an issue with the transactions. Here is a fixed version. Note what I commented out and how I changed it.

    https://gist.github.com/4390181
  • mkhuda #
    Commented on 12-27-2012 at 2:15 PM
    Wow, amazing !
    Thank you very much !
  • Anthony #
    Commented on 01-30-2013 at 9:24 AM
    Hi Ray, I haven't used the Parse JS api but the IOS api has a "saveEventually" method that tries to send the object immediately to parse and if a network connection is not available the object is stored locally in an on-disk cache until it can be delivered to Parse.
  • Commented on 01-30-2013 at 9:39 AM
    Just checked and it doesn't exist for JS. I bet you could add support for something like this. Just add the obs to a queue and ping the network every 5 minutes. Or listen for an online event.
  • xavier #
    Commented on 02-21-2013 at 11:00 PM
    Thanks for the great tutorial. I am planning my mobile app in such a way that data from our main database will be pushed to Parse and the mobile app will only interact with the data in Parse and will not hit our main database. End of the day, there will be a "download" from Parse to the main database also to keep things synched.

    I guess i will have to use Parse.com's Rest API for the data movement back and forth from our database to Parse. I would like to use Coldfusion queries for this. Parse has examples with Curl and Python. So, just reaching out to you for your thoughts on this. Thanks in advance for your time
  • Commented on 02-22-2013 at 5:48 AM
    I could have sworn I had shown an example of this before, but I couldn't find it. Will make a simple demo today.
  • xavier #
    Commented on 02-22-2013 at 10:09 AM
    Thanks for your time and attention. Looking forward to it.
  • Commented on 02-22-2013 at 10:12 AM
    Xavier, please check out this: http://www.raymondcamden.com/index.cfm/2013/2/22/I...
  • Commented on 04-26-2013 at 1:58 AM
    I remembered this article,
    and I thank you for helping complete the final project in my college.

    Thanks, Mr. Raymond for your teaching ! :)
  • Commented on 04-26-2013 at 5:28 AM
    You are most welcome.
  • muhaimin cs #
    Commented on 07-22-2013 at 3:52 AM
    i just test your sample from download file. It seems your sample has created 2 same object of Web SQL. Is it bcos i refresh the page? One more thing how do i let the page know the connection to internet is ready. Thanks
  • Commented on 07-22-2013 at 6:39 AM
    If you are offline and save two things then yes you will get two objects. Outside of that I may not be reading you right.

    As for letting the page know a connection is ready, you can use the online/offline event handlers. My app would be improved if it noted that.
  • muhaimin cs #
    Commented on 07-22-2013 at 11:01 PM
    how about if user close the safari, will the saved data still available in Web SQL?
  • muhaimin cs #
    Commented on 07-23-2013 at 12:52 AM
    sorry to bother you again. how about associate the entries with a photo snap on tablet?
  • Commented on 07-23-2013 at 6:45 AM
    WebSQL persists, yes.
    Your second comment doesn't make sense to me.
  • muhaimin cs #
    Commented on 07-24-2013 at 8:24 PM
    thanks raymond
  • Georges #
    Commented on 09-29-2013 at 9:58 AM
    hey awesome post . i just have one question though.
    if i want to load images from object how do i do it ?
    i added this code as it is described in parse.com but didn't work .
    s+= '<b>ID:</b> '+ result.imagePlaceholder.url() + '<br/>';

    any thoughts ? Thanks
  • Commented on 09-30-2013 at 3:16 PM
    Hmm - have you tried what I did here - http://www.raymondcamden.com/index.cfm/2013/7/10/Q...
  • Commented on 11-12-2013 at 5:18 AM
    Hi Raymond,
    Thank you for your code. I try to send Sighting to your parse, have sightName : Joker there?

    I just want try to connect database. I can not connect parse n codeigniter with javascript. Could you help me? Thanks
  • Commented on 11-12-2013 at 5:27 AM
    You should be able to check the response via your browser dev tools. If you don't see a successful response, then it didn't work.

    As for CodeIgniter, I don't use it.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty