This mini series about “Offline Web Applications” shows you how to build a web application that your users can use while they are offline. I will give a session about this topic at Herbstcampus 2012.
- Part 1 showed you the web application that should be available offline - but isn't yet.
- Part 2 showed you how to use the HTML 5 application cache to make all resources available offline.
- You are reading part three, where we will develop the new application logic in JavaScript.
- Part 4 will make the application logic available offline using IndexedDB and the IndexedDB JQuery plugin.
JQuery, document.ready
We start by including some JavaScript in the dictionary page. The submit button needs an ID. We will implement the functions “loadDictionaryContent” and “submitDictionaryEntry” in the file “dicitionary.js”.
dictionary.html
<head> <!-- ... --> <script src="jquery-1.8.0.min.js"></script> <script src="dictionary.js"></script> <script> $(document).ready(function() { loadDictionaryContent(); $('#submitButton').click(function() { submitDictionaryEntry($('#addForm').serialize()); return false; }); }); </script> </head> <body> <!-- ... --> <input type="submit" value="Add" id="submitButton"/> <!-- ... --> </body>
dictionary.js
The JavaScript file implements the two functions “loadDictionaryContent” and “submitDictionaryEntry”. These use AJAX to call the backend to load the dictionary content and to save new words.
loadDictionaryContent = function() { $.ajax({ url:'api/listEntries' }).done(function(data) { $(wordsList).empty(); var dataArray = JSON.parse(data); $.each(dataArray, function(index, value) { $(wordsList).append('<div class="left">' + value.german + '</div>'); $(wordsList).append('<div class="right">' + value.austrian + '</div>'); $(wordsList).append('<div class="clear"></div>'); }); }); }; submitDictionaryEntry = function(formContent) { $.ajax({ url:'api/newEntry', type: 'GET', data: formContent }).done(function(data) { loadDictionaryContent(); }); };
API
We have to create the two API endpoints “api/listEntries” and “api/newEntry” in the backend. I use wicket pages to implement them. In a real project you should probably use a REST library.
ListEntries.java
public class ListEntries extends Page { private static final long serialVersionUID = 1L; @Inject private DictionaryService dictionaryService; public ListEntries() { } @Override public void renderPage() { List<DictionaryWordEntity> entries = dictionaryService.listAllEntries(); String entriesJson = new Gson().toJson(entries); PrintWriter w = new PrintWriter(getResponse().getOutputStream()); w.println(entriesJson); w.close(); } }
NewEntry.java
public class NewEntry extends Page { private static final long serialVersionUID = 1L; @Inject private DictionaryService dictionaryService; public NewEntry(PageParameters params) { String german = params.get("german").toString(""); String austrian = params.get("austrian").toString(""); dictionaryService.addWord(german, austrian); } @Override public void renderPage() { } }
DictionaryApplication.java
public class DictionaryApplication extends WebApplication { @Override protected void init() { //... mountPage("api/listEntries", ListEntries.class); mountPage("api/newEntry", NewEntry.class); } }
Cache Manifest
We have to update the cache manifest to include the 2 new javascript files. We also have to add the 2 API endpoints to the “NETWORK” section so the browser knows to request them online. You might notice that the browser does not update any “CACHE”d resources when the cache manifest is unchanged. To be able to control when the browser updates these resources we add a “version” comment that we increment every time a resource has changed. You should increment this version automatically during your build or deployment process in a real project. For this example manually incrementing the version number is good enough.
offline.manifest
CACHE MANIFEST # Offline cache manifest for the dictionary application # version 1 CACHE: dictionary.html style.css jquery-1.8.0.min.js dictionary.js NETWORK: api/listEntries api/newEntry
Coming up next...
And that’s it: The dictionary application works again! And it is still available offline. But it still does not work in offline mode. For this we need to load all data into an offline data base. Stay tuned for part 4 where we will finish the application and make everything available offline!