Can you use HTML5 technologies to build a web application which works offline? Without a reliable internet connection? Let’s say for two weeks?
That is what our client asked us to build. Their people will use the application on the road; reading documents, entering results and uploading pictures. And then they come home, connect to the internet and sync their results with their colleagues’.
AppCache, IndexedDB and File API allow us to store the application and its data in the browser. However, they require us to re-think assumptions we used to make in the web: Is the client or the server the master of the data? How can we handle updates of the application? What data do we need to download beforehand? How do you test offline automatically? And what does offline mean anyway?
We want to show you what we discussed and how we answered these questions.
OnConnectionLost: The life of an offline web application - JSUnconf 2015
1. J S U n c o n f 2 0 1 5
ON CONNECTION LOST
The life of an offline web application &
war stories about generating PDFs in the browser
#jsunconf #offlinefirst
@thoughtworks
@sgrewenig @jthoenes
34. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
35. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
36. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
37. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
38. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
39. 10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly');
32 var store = trans.objectStore('name');
33 var getRequest = store.get('4');
34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount');
43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15));
44 cursorRequest.onsuccess = // ...
THE API
66. "sections": [{
"blocks": [{
"contentItems": [
{
"uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"wysiwyg": "<p>Decorative <i>deer</i> figures in a set of 2</p><img our-
src=“aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.png”>”
},
{
"libraryItemUid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"wysiwyg": "<p>There may be <strong>no sign</strong> of a seam in the
material. [FT-PLACEHOLDER]</p>"
},
{
"libraryItemUid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"wysiwyg": "<p>Set comprises a large deer and a small deer [FT-
69. var doc = new jsPDF();
doc.text(20, 20, 'Hello world.');
doc.save('Test.pdf');
https://github.com/MrRio/jsPDF
70. PDFDocument = require 'pdfkit'
doc = new PDFDocument
doc.pipe fs.createWriteStream('output.pdf')
doc.font('fonts/PalatinoBold.ttf')
.fontSize(25)
.text('Some text with an embedded font!', 100, 100)
doc.addPage()
.fontSize(25)
.text('Here is some vector graphics...', 100, 100)
doc.end()
https://github.com/devongovett/pdfkit
71. pdfMake.createPdf({
content: [
{ text: 'This paragraph will have a bigger font', fontSize: 15 },
{
text: [
{ text: 'restyle part of it and make it bigger ', fontSize: 15 },
'than the rest.'
]
}
]
}).open();
https://github.com/bpampuch/pdfmake