1. 程式人生 > >HTML5新特性之離線快取技術實戰

HTML5新特性之離線快取技術實戰

八、離線Web應用實戰。

通過一個簡單的記事本程式——PermaNote,來解釋如何使用。程式將使用者的文字儲存到localStorage中,並且在網路連線可用的時候,

將其上傳到伺服器,PermaNote只允許使用者編輯單個筆記。

PermaNote應用包含3個檔案,一個應用清單檔案、一個html頁面檔案,一個實現邏輯的js檔案。

Demo: http://xuanfengge.com/demo/201506/appcache/permanote.html

①.premanote.appcache部分:


CACHE MANIFEST
#  PermaNote v8
permanote.html
permanote.js
NETWORK:
note
②.permanote.html部分:

<!DOCTYPEHTML>
<html manifest= permanote.appcache”>
     <head>
          <title>PermaNote Editor</title>
          <script src=” permanote.js”></script>
           <style type=”text/css”>
                 #editor {width:100%;height:250px}
                 #statusline{width:100%}
            </style>
      </head>
       <body>
               <div id=”toobar”>
                    <button id=”savebutton”onclick = “save()”>save</button>
                    <button onclick = “sync()”>SyncNote</button>
                    <button onclick = “applicationCache.update()”>UpdateApplication</button>
                      <textarea id=”editor”></textarea>
                       <div id=”statusline”></div>
               </div>
      </body>
</html>

③.permanote.js部分
status()函式用於顯示狀態列訊息,save()函式將筆記本儲存到伺服器,sync()用於確保本地與伺服器文字的同步。

應用程式的時間處理程式解釋:

(1).onload

嘗試和伺服器同步,一旦有新版本的筆記並且完成同步後,就啟用編輯器視窗。

save()和sync()函式發出HTTP請求,並在XMLHttpRequest物件上註冊一個onload時間處理程式來獲取上傳或者

下載完成的提醒。

(2).onbeforeunload

在未上傳前,把當前版本的筆記資料儲存到伺服器上。

(3).oninput

每當textarea輸入框內容發生變化時,都將其內容儲存到localStorage中,並啟動一個計時器。當用戶停止編輯超過5秒

,將自動把資料儲存到伺服器。

(4).onoffline

當瀏覽器進入離線狀態時,在狀態列顯示離線訊息。

(5).ononline
當瀏覽器回到線上狀態時,同步伺服器,檢查是否有新版本的資料,並且儲存當前版本的資料。

(6).onupdateready

如果新版本的應用已快取,則在狀態列展示訊息告知使用者。

(7).onnoupdate

// 定義全域性變數
var editor, statusline, savebutton, idletimer;
 
// 首次載入應用
window.onload = function() {
    // 第一次載入時,初始化本地儲存
    if (localStorage.note == null) localStorage.note = "";
    if (localStorage.lastModified == null) localStorage.lastModified = 0;
    if (localStorage.lastSaved == null) localStorage.lastSaved = 0;
 
    // 查詢編輯器UI元素,並初始化全域性變數
    editor = document.getElementById("editor");
    statusline = document.getElementById("statusline");
    savebutton = document.getElementById("savebutton");
 
    editor.value = localStorage.note; // 初始化編輯器,將儲存的筆記資料填充到內容
    editor.disabled = true;           // 同步前禁止編輯
 
    // 當輸入框內容發生變化
    editor.addEventListener("input",
                            function (e) {
                                // 將新的內容儲存至localStorage
                                localStorage.note = editor.value;
                                localStorage.lastModified = Date.now();
                                // 重置閒置計時器
                                if (idletimer) clearTimeout(idletimer);
                                idletimer = setTimeout(save, 5000);
                                // 啟用儲存按鈕
                                savebutton.disabled = false;
                            },
                            false);
 
    // 每次載入應用程式時,嘗試同步伺服器
    sync();
};
 
// 離開頁面錢儲存資料到伺服器
window.onbeforeunload = function() {
    if (localStorage.lastModified > localStorage.lastSaved)
        save();
};
 
// 離線時,告知使用者
window.onoffline = function() { status("Offline"); }
 
// 再次返回線上狀態時,進行同步
window.ononline = function() { sync(); };
 
// 當有新版本應用的時候,提醒使用者
// 也可使用location.reload()放大來強制重新整理應用
window.applicationCache.onupdateready = function() {
    status("A new version of this application is available. Reload to run it");
};
 
// 當沒有新版本的時候也通知使用者
window.applicationCache.onnoupdate = function() {
    status("You are running the latest version of the application.");
};
 
// 狀態列顯示相關資訊提示
function status(msg) { statusline.innerHTML = msg; }
 
// 每當筆記本內容更新後,如果使用者停止編輯超過5分鐘
// 就會自動將筆記文字上傳至伺服器(線上狀態下)
function save() {
    if (idletimer) clearTimeout(idletimer);
    idletimer = null;
 
    if (navigator.onLine) {
        var xhr = new XMLHttpRequest();
        xhr.open("PUT", "/note");
        xhr.send(editor.value);
        xhr.onload = function() {
            localStorage.lastSaved = Date.now();
            savebutton.disabled = true;
        };
    }
}
 
// 檢查服務端是否有新版本的筆記,若無,則將當前版本儲存到伺服器端
function sync() {
   if (navigator.onLine) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "/note");
        xhr.send();
        xhr.onload = function() {
            var remoteModTime = 0;
            if (xhr.status == 200) {
                var remoteModTime = xhr.getResponseHeader("Last-Modified");
                remoteModTime = new Date(remoteModTime).getTime();
            }
 
            if (remoteModTime > localStorage.lastModified) {
                status("Newer note found on server.");
                var useit =
                    confirm("There is a newer version of the note\n" +
                            "on the server. Click Ok to use that version\n"+
                            "or click Cancel to continue editing this\n"+
                            "version and overwrite the server");
                var now = Date.now();
                if (useit) {
                    editor.value = localStorage.note = xhr.responseText;
                    localStorage.lastSaved = now;
                    status("Newest version downloaded.");
                }
                else 
                    status("Ignoring newer version of the note.");
                localStorage.lastModified = now;
            }
            else
                status("You are editing the current version of the note.");
 
            if (localStorage.lastModified > localStorage.lastSaved) {
                save();
            }
 
            editor.disabled = false;  // 再次啟用編輯器
            editor.focus();           // 將游標定位到編輯器中
        }
    }
    else { // 離線狀態下,不能同步
        status("Can't sync while offline");
        editor.disabled = false;
        editor.focus();
    }
}