Skip to content

Instantly share code, notes, and snippets.

@rehnen
Last active December 24, 2015 22:49
Show Gist options
  • Save rehnen/6875841 to your computer and use it in GitHub Desktop.
Save rehnen/6875841 to your computer and use it in GitHub Desktop.
rapport.md

Webapplikationer offline

Hur HTML5 kan hjälpa användande av webapplikationer offline

Introduktion

Den här texten syftar till att berätta om några av de nya HTML5 tekniker som kan hjälpa till vid användande av webbapplikationer utan att ha en konstant anslutning till webbservern. Hur kan de nya webteknikerna hjälpa till?

Bakgrund

HTML5 anses av många vara framtiden för webbutveckling och standardiseringsorganet V3C har satt år 2014 året då HTML5 blir standard för webben. När man pratar om HTML5 så tänker kanske många först och främst på multimedia och de taggar som möjliggör uppspelning av multimedia så som video och audio taggar. Nämner man också javascript så kanske många tänker spel skrivna i javascript, eller på hur man kan använda javascript i relation till de tidigare nämnda multimediataggarna. HTML5 har kanske sålts till många som ett alternativ till flash och andra plugins till webbläsaren. Är man lite mer påläst så har man kanske hört talas websockets, eller det vi ska tala om nu nämnligen hur man hanterar att göra en webplats tillgänglig och användbar även offline.

Syfte och mål

Målet är att utreda om man kan lagra information så som formulärdata och filer lokalt i sin webbläsare. Hur bär man sig i så fall åt? Går det att göra inom ramarna för HTML5 standarden?

Förhoppningen är att kunna visa på ett fåtal tekniker som kan hjälpa användaren att lagra data i sin browser. Sammt att kunna utreda hur nära dessa tekniker kan komma att skapa en applikation som hjälper användaren i vårt usecase att utföra sitt arbete även när han inte är konstant ansluten till internet.

Forskningsfråga

Går det att utveckla en webapplikation för Google Chrome som går att använda även offline? Kan man komma åt en webapplikation även när man inte har anslutning till webbservern den ligger på? Hur mycket får man spara hos klienten?

Metodik

För att besvara forskningsfrågan utförs en litteraturstudie där HTML5 standarden granskas för att finna vilka tekniker som kan tänkas hjälpa vid lokal lagrig och hur bra stöd det finns för dem i nuläget.

En webbapplikation byggs för att visa upp några passande tekniker och beskriva var de befinner sig i nuläget. HTML5 är 2013, trots allt inte riktigt i mål ännu, det blir som bekant standard först 2014.

Experimentdesign

Usecase

Användaren sitter på ett flygplan som befinner sig på öppet vatten mellan London och New York. Internetanslutning har han/hon inte haft sedan flygplanet lyfte, men användaren behöver fortsätta jobba på flygplanet. Det användaren hade behövt göra i just det här fallet är att på sin bärbara dator planera in lite möten med en webapplikation, han/hon vill dessutom kunna ladda upp en fil som ska användas under mötet.

Traditionellt sätt så hade användaren varit begränsad till att bara skriva ner allt han/hon hade velat ladda upp och sedan föra in det i systemet när en anslutning till servern kan upprättas. Långsamt. Krångligt. Besvärligt.

Det som användaren bör erbjudas är en applikation som kan sparas i webbläsaren och som sparar hans/hennes arbete lokalt när ingen anslutning till servern existerar. Och det här arbetet syftar alltså till att ta reda på om och i så fall hur det skulle kunna gå till att skapa en sådan applikation.

På serversidan

På serversidan körs skriptspråket PHP och databasen MySQL, vilket är en väldigt vanlig kombination för webbservrar.

I det här arbetet läggs inte speciellt mycket vilket vid teknikerna på serversidan av applikationen då offline i kontexten av det här arbetet syftar till att arbeta lokalt. Alltså på klientsidan. Serversidan i min applikation syftar bara till att ta emot data från klienten, dekoda datan och lagra den i databasen. Arbetet syftar inte till att hämta datan från servern, då det ligger utanför arbetets kontext då arbetet handlar on HTML5 tekniker som underlättar för offlinearbete.

På klientsidan

IndexedDB

Med HTML5 introducetas en ny databas för klientsidan, nämnligen IndexedDB som medföljer flertalet av de moderna borwsers som används idag. IndexedDB är till för att göra det enklare att spara ner data lokalt hos användaren och därmed så kan användaren slippa att tanka ner tunga filer fler än en gång. Man kan även spara information som användaren matat in tidigare exempelvis i olika formulär för att se till att användaren har dem tillgängliga när han besöker platsen igen.

IndexedDB är en kolumnbaserad databas som inte struktureras med hjälp av tabeller, så som i en SQL-databas. Istället används json-objekt som är lite mer flexibla i sin natur. Json är en förkortning av JavaScript object notation. Till skillnad från i en sqlbaserad databas som tydligt definierar vad som ska stoppas in i varje rad i sina tabeller så har inte IndexedDB några krav på att det som matas in i databasens olika objectstores(motsvarigheten till tabell) följer en definierad struktur. Objeken som stoppas in kan variera i allt från de datatyper som objektens keys(kolumner) håller, hur mycket som lagras i varje key och hur många keys som fins i objektet.

Det fanns tankar på att en databas vid namn WebSQL skulle bi en del av standarden, men den idén ratades för att de som skapar webbläsare inte kunde enas om en sqlstandard och för att de ville ha en mer "javascriptig" databas.

Öppna IndexedDB

Att öppna en indexedDB databas görs med funktionen "open".

//I detta exempel kallar vi funktionen open för att öppna databasen vid namn myIndexedDB, trean syftar till vilken version av databasen vi använder
//Notera att databasen inte måste finnas innan funktionen kallas första gången
var openRequest = indexedDB.open("myIndexedDB", 3);
var db = {};

När funktionen open kallas så finns det fyra funktioner som kan behöva kallas

onupgradeneeded

Funktionen onupgradeneeded kallas i när databasen inte redan existerar och därmed behöver skapas. Det är också där vi passar på att skapa våra index för objectstore. För den som är van vi en mer traditionell databas så som mySQL eller MSSQL så kan man se dem lite som kolumner fasst med en vissa skillnader. Två påfallande skillnader är att våra index är typsvaga och inte att vi använder en specifik datatyp. I indexet file så placerar jag utan besvär ett jsonobjekt om innehåller ett flertal variabler.

openRequest.onupgradeneeded = function (e) {
    db = e.target.result;
    var objectStore = db.createObjectStore("meetings", {keyPath: "id", autoIncrement: true});
    objectStore.createIndex("title", "title", {unique: false});
    objectStore.createIndex("text", "text", {unique: false});
    objectStore.createIndex("file", "file", {unique: false});
}

onsuccess

Denna funktion kallas när databasen redan existerar och öppnandet av sagd databas sker utan bekymmer.

openRequest.onsuccess = function(e){
    //Vi kommer framöver att komma åt vår databas via den globala variabeln db som vi skapade tidigare.
    db = e.target.result;
}

onerror

När något går snett.

openRequest.onerror = function(e){
 	console.log("openRequest error");
 }

onblocked

Onblocked kallas när användaren stäng av IndexedDB i sin webbläsare. I mitt fall så väljer jag att inte hantera detta fall mer än att jag skriver ut att det har skett i konsolen.

 openRequest.onblocked = function(e){
 	console.log("openRequest blocked");
 }

Skriva till IndexedDB

För att skriva till databasen måste vi använda oss av en transaktion. Vi ber om att få gåra en transaktion till det objectstore som vi skapade tidigare.

När man kommit åt sitt objectstore så placerar man helt enkelt det värde man vill spara i databasen. I exemplet under placerar vi en variabel i databasen i en key som utpekas av variabeln key.

var transaction = db.transaction(["meetings"], "readwrite");
var store = transaction.objectStore("meetings");
//data är det värde som ska sparas ner i objectstore, key pekar på ett index
store.put(data, key);

Funktionen för att hantera resultatet av att kalla på put så behöver vi funktionerna onerror och onsuccess.

Läsa från IndexedDB

Läsning av data i IndexedDB kan ske på två olika vis, antingen så anger man ett sökord som refererar till en key i tabellen man vi söka i eller så använder man sig av en så kallad cursor som stegar genom hela tabellen.

var transaction = db.transaction(["meetings"]);
var objectStore = transaction.objectStore("meetings");
objectstore.get(searchword);

Filhantering i HTML5

Tidigare nämndes filuppladdning även när man är offline. Det går naturligtvis inte att ladda upp en fil till en server utan att klienten har en anslutning till den. Vad som går att göra är att läsa innehållet ur en lokal fil in i webläsaren och att sedan spara filens namn, typ och innehåll i indexed db. Koden under visar hur man kan läsa innehållet från från ett htmlformulär med javascript.

var file = document.getElementById("file").files[0];
var reader =  new FileReader();

reader.onloadend = function(){
    var fileContent = readet.result;
    
}

var fileAsBin = reader.readAsDataURL(file);

Offline cache

För att en användare ska kunna komma åt sin applikation när den är offline så behöver vi spara ner de delar vi tänkt använda lokalt. För att specificera vad vi vill att användaren ska spara ner så skapar vi en fil vid namn .manifest och länkar till den i vår html kod på följande sätt.

<html manifest="main.manifest">

Väl inne i vår manifestfil så specificerar vi de delarna som ska sparas lokalt. I mitt fall så väljer jag att spara ner min stylesheet, html kod och all den javascript jag kommer att behöva för att kunna köra applikationen. Alla manifestfiler börjar med textraden CACHE MANIFEST, brädgård betyder kommentar och allt efter CACHE: är sådant som sparas lokalt.

Nedan följer hela min manifestfil.

CACHE MANIFEST
# v1

CACHE:
index.php
style.less
main.js

../mall/header.php
../mall/footer.php
../mall/mos.js
../mall/base.less
../js/less.js

http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js

Min applikation

Bild 1. - Min applikation För att visa möjligheterna med tidigare nämnda tekniker, skrevs ett simpelt program som kan ses på bilden ovan.

Användaren uppmanas att skriva in en titel, en sammanfattning och ladda upp en bild. Allt med ett helt vanligt HTML formulär. När användaren trycker på send knappen "send" i formuläret så triggas en funktion som ser till att allt användaren matat formuläret med(inklusive bilden) hamnar i den lokala IndexedDB databasen, delar av vars innehåll visas i tabellen till höger om formuläret.

När man trycker på "Send" under tabellen så kommer det att skicka över innehållet i databasen rad för rad med hjälp av till en webbserver som kör PHP och MySQL. Där kommer informationen att sparas mer permanent.

Under själva applikation visas det verktyg som Chrome använder för att visa innehållet i den lokala databasen.

Koden för applikationen finns på https://github.com/rehnen/html5-offline-demo/tree/master/form för den som vill läsa.

Lagringsbegränsningar

När man läser google cromes specifikationer om lagring så finner man att App Cache och IndexedDB inte har någon riktig begränsning, men om man vill lagra mycket så måste man be användaren om lov och requesta hur mycket hur mycket utrymme man behöver.

Slutsats

IndexedDB klarar av att lagra data så som filer och formulärdata. När man har cachat applikationen kan man använda den offline utan bekymmer. Och med Ajax kan man sedan skicka iväg datan från indexedDB till sin webserver.

Länkar

Written with StackEdit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment