function initialize()
{// initialize the DHTML History // framework dhtmlHistory.initialize();
// subscribe to DHTML history change // events dhtmlHistory.addListener(historyChange);
// if this is the first time we have // loaded the page... if dhtmlHistory.isFirstLoad()) {debug("Adding values to browser "+ "history", false);
// start adding history dhtmlHistory.add("helloworld","Hello World Data");
dhtmlHistory.add("foobar", 33);
dhtmlHistory.add("boobah", true);
var complexObject = new Object();
complexObject.value1 = "This is the first value";
complexObject.value2 = "This is the second data";
complexObject.value3 = new Array();
complexObject.value3[0] = "array 1";
complexObject.value3[1] = "array 2";
dhtmlHistory.add("complexObject",complexObject);
在add()方法被調用后,新地址立刻被作為一個錨值顯示在用戶的瀏覽器的URL欄里。例如,一個AJAX web頁面停留在http://codinginparadise.org/my_ajax_app,調用了dhtmlHistory.add("helloworld", "Hello World Data" 后,用戶將在瀏覽器的URL欄里看到下面的地址
http://codinginparadise.org/my_ajax_app#helloworld
然后他們可以把這個頁面做成書簽,如果他們使用這個書簽,你的AJAX應用可以讀出#helloworld值然后使用她去初始化web頁面。Hash里的地址值被Really Simple History 框架顯式的編碼和解碼(URL encoded and decoded) (這是為了解決字符的編碼問題)
對當AJAX地址改變時保存更多的復雜的狀態來說,historyData 比一個更容易的匹配一個URL的東西更有用。他是一個可選的值,可以是任何javascript類型,比如Number, String, 或者 Object 類型。有一個例子是用這個在一個多文本編輯器(rich text editor)保存所有的文本,例如,如果用戶從這個頁面漂移(或者說從這個頁面導航到其他頁面,離開了這個頁面)走。當一個用戶再回到這個地址,瀏覽器會把這個對象返回給歷史改變偵聽器(history change listener)。
開發者可以提供一個完全的historyData 的javascript對象,用嵌套的對象objects和排列arrays來描繪復雜的狀態。只要是JSON (JavaScript Object Notation) 允許的那么在歷史數據里就是允許的,包括簡單數據類型和null型。DOM的對象和可編程的瀏覽器對象比如XMLHttpRequest ,不會被保存。注意historyData 不會被書簽持久化,如果瀏覽器關掉,或者瀏覽器的緩存被清空,或者用戶清除歷史的時候,會消失掉。
使用dhtmlHistory 最后一步,是isFirstLoad() 方法。如果你導航到一個web頁面,再跳到一個不同的頁面,然后按下回退按鈕返回起始的網站,第一頁將完全重新裝載,并激發onload事件。這樣能產生破壞性,當代碼在第一次裝載時想要用某種方式初始化頁面的時候,不會再刷新頁面。isFirstLoad() 方法讓區別是最開始第一次裝載頁面,還是相對的,在用戶導航回到他自己的瀏覽器歷史中記錄的網頁時激發load事件,成為可能。
在例子代碼中,我們只想在第一次頁面裝載的時候加入歷史事件,如果用戶在第一次裝載后,按回退按鈕返回頁面,我們就不想重新加入任何歷史事件。
window.onload = initialize;
function initialize()
{
// initialize the DHTML History
// framework dhtmlHistory.initialize();
// subscribe to DHTML history change
// events dhtmlHistory.addListener(historyChange);
// if this is the first time we have
// loaded the page...
if (dhtmlHistory.isFirstLoad())
{
debug("Adding values to browser "+ "history", false);
// start adding history dhtmlHistory.add("helloworld","Hello World Data"); dhtmlHistory.add("foobar", 33);
dhtmlHistory.add("boobah", true);
var complexObject = new Object();
complexObject.value1 ="This is the first value";
complexObject.value2 ="This is the second data";
complexObject.value3 = new Array();
complexObject.value3[0] = "array 1";
complexObject.value3[1] = "array 2";
dhtmlHistory.add("complexObject",complexObject);
讓我們繼續使用historyStorage 類。類似dhtmlHistory ,historyStorage通過一個叫historyStorage的單一全局對象來顯示他的功能,這個對象有幾個方法來偽裝成一個hash table, 象put(keyName, keyValue), get(keyName), and hasKey(keyName).鍵名必須是字符,同時鍵值可以是復雜的javascript對象或者甚至是xml格式的字符。在我們源碼source code的例子中,我們put() 簡單的XML 到historyStorage 在頁面第一次裝載時。
window.onload = initialize;
function initialize()
{
// initialize the DHTML History
// framework dhtmlHistory.initialize();
// subscribe to DHTML history change
// events dhtmlHistory.addListener(historyChange);
// if this is the first time we have
// loaded the page... if (dhtmlHistory.isFirstLoad())
{
debug("Adding values to browser "+ "history", false);
// start adding history dhtmlHistory.add("helloworld","Hello World Data");
dhtmlHistory.add("foobar", 33);
dhtmlHistory.add("boobah", true);
var complexObject = new Object();
complexObject.value1 ="This is the first value";
complexObject.value2 ="This is the second data";
complexObject.value3 = new Array();
complexObject.value3[0] = "array 1";
complexObject.value3[1] = "array 2";
dhtmlHistory.add("complexObject", complexObject);
// cache some values in the history
// storage debug("Storing key 'fakeXML' into "+ "history storage", false);
var fakeXML ='<?xml version="1.0" '+'encoding="ISO-8859-1"?>'+'<foobar>'+'<foo-entry/>'+'</foobar>';
historyStorage.put("fakeXML", fakeXML);
}
然后,如果用戶從這個頁面漂移走(導航走)又通過返回按鈕返回了,我們可以用get()提出我們存儲的值或者用haskey()檢查他是否存在。
window.onload = initialize;
function initialize()
{
// initialize the DHTML History
// framework dhtmlHistory.initialize();
// subscribe to DHTML history change
// events dhtmlHistory.addListener(historyChange);
// if this is the first time we have
// loaded the page... if (dhtmlHistory.isFirstLoad())
{
debug("Adding values to browser "+ "history", false);
// start adding history dhtmlHistory.add("helloworld","Hello World Data"); dhtmlHistory.add("foobar", 33);
dhtmlHistory.add("boobah", true);
var complexObject = new Object();
complexObject.value1 ="This is the first value";
complexObject.value2 ="This is the second data";
complexObject.value3 = new Array();
complexObject.value3[0] = "array 1";
complexObject.value3[1] = "array 2";
dhtmlHistory.add("complexObject",complexObject);
// cache some values in the history
// storage debug("Storing key 'fakeXML' into " + "history storage", false);
var fakeXML ='<?xml version="1.0" '+'encoding="ISO-8859-1"?>'+'<foobar>'+'<foo-entry/>'+'</foobar>';
historyStorage.put("fakeXML", fakeXML);
}
// retrieve our values from the history
// storage var savedXML =historyStorage.get("fakeXML");
savedXML = prettyPrintXml(savedXML);
var hasKey =historyStorage.hasKey("fakeXML");
var message ="historyStorage.hasKey('fakeXML')="+ hasKey + "<br>"+ "historyStorage.get('fakeXML')=<br>"+ savedXML; debug(message, false);}
prettyPrintXml() 是一個第一在例子源碼full example source code中的工具方法。這個方法準備簡單的xml顯示在web page ,方便調試。
注意數據只是在使用頁面的歷史時被持久化,如果瀏覽器關閉了,或者用戶打開一個新的窗口又再次鍵入了ajax應用的地址,歷史數據對這些新的web頁面是不可用的。歷史數據只有在用前進或回退按鈕時才被持久化,而且在用戶關閉瀏覽器或清空緩存的時候會消失掉。想真正的長時間的持久化,請看Ajax MAssive Storage System (AMASS).
我們的簡單示例已經完成。演示他(Demo it)或者下載全部的源代碼(download the full source code.)
示例2
我們的第2個例子是一個簡單的模擬ajax email 應用的示例,叫O'Reilly Mail,類似Gmail. O'Reilly Mail描述了怎樣使用dhtmlHistory類去控制瀏覽器的歷史,和怎樣使用historyStorage對象去緩存歷史數據。
O'Reilly Mail 用戶接口(user interface)有兩部分。在頁面的左邊是一個有不同email文件夾和選項的菜單,例如 收件箱,草稿,等等。當一個用戶選擇了一個菜單項,比如收件箱,我們用這個菜單項的內容更新右邊的頁面。在一個實際應用中,我們會遠程取得和顯示選擇的信箱內容,不過在O'Reilly Mail里,我們簡單的顯示選擇的選項。
O'Reilly Mail使用Really Simple History 框架向瀏覽器歷史里加入菜單變化和更新地址欄,允許用戶利用瀏覽器的回退和前進按鈕對應用做書簽和跳到上一個變化的菜單。
我們加入一個特別的菜單項,地址簿,來描繪historyStorage 能夠怎樣被使用。地址簿是一個由聯系的名字電子郵件和地址組成的javascript數組,在一個真實的應用里我們會取得他從一個遠程的服務器。不過,在O'Reilly Mail里,我們在本地創建這個數組,加入幾個名字電子郵件和地址,然后把他們存儲在historyStorage 對象里。如果用戶離開了這個web頁面以后又返回的話,O'Reilly Mail應用重新從緩存里得到地址簿,勝過(不得不)再次訪問遠程服務器。
地址簿是在我們的初始化initialize()方法里存儲和重新取得的
/** Our function that initializes when the page is finished loading. */
function initialize()
{
// initialize the DHTML History framework dhtmlHistory.initialize();
// add ourselves as a DHTML History listener dhtmlHistory.addListener(handleHistoryChange);
// if we haven't retrieved the address book
// yet, grab it and then cache it into our
// history storage if (window.addressBook == undefined)
{
// Store the address book as a global
// object.
// In a real application we would remotely
// fetch this from a server in the
// background.window.addressBook =["Brad Neuberg 'bkn3@columbia.edu'","John Doe 'johndoe@example.com'", "Deanna Neuberg 'mom@mom.com'"];
// cache the address book so it exists
// even if the user leaves the page and
// then returns with the back buttonhistoryStorage.put("addressBook",addressBook);
}
else
{
// fetch the cached address book from
// the history storage window.addressBook =historyStorage.get("addressBook");
}
處理歷史變化的代碼是簡單的。在下面的代碼中,當用戶不論按下回退還是前進按鈕handleHistoryChange 都被調用。我們得到新的地址(newLocation) 使用他更新我們的用戶接口來改變狀態,通過使用一個叫displayLocation的O'Reilly Mail的工具方法。
/** Handles history change events. */function handleHistoryChange(newLocation,historyData) {
// if there is no location then display
// the default, which is the inbox if (newLocation == "") {newLocation = "section:inbox";
}
// extract the section to display from
// the location change; newLocation will
// begin with the word "section:" newLocation =newLocation.replace(/section\:/, "");
// update the browser to respond to this
// DHTML history change displayLocation(newLocation, historyData);
}/** Displays the given location in the right-hand side content area. */function displayLocation (newLocation,sectionData)
{
// get the menu element that was selected var selectedElement =document.getElementById(newLocation); // clear out the old selected menu item var menu = document.getElementById("menu");
for (var i = 0; i < menu.childNodes.length; i++)
{
var currentElement = menu.childNodes[i];
// see if this is a DOM Element node if (currentElement.nodeType == 1)
{
// clear any class name currentElement.className = "";
}
}
// cause the new selected menu item to
// appear differently in the UI selectedElement.className = "selected";
// display the new section in the right-hand
// side of the screen; determine what
// our sectionData is
// display the address book differently by
// using our local address data we cached
// earlier if (newLocation == "addressbook")
{
// format and display the address book sectionData = "<p>Your addressbook:</p>";
sectionData += "<ul>";
// fetch the address book from the cache
// if we don't have it yet
if (window.addressBook == undefined)
{
window.addressBook =historyStorage.get("addressBook");
}
// format the address book for display
for (var i = 0;i < window.addressBook.length;
i++)
{
sectionData += "<li>"+ window.addressBook[i]+ "</li>";
}
sectionData += "</ul>";
}
// If there is no sectionData, then
// remotely retrieve it; in this example
// we use fake data for everything but the
// address book if (sectionData == null)
{
// in a real application we would remotely
// fetch this section's content sectionData = "<p>This is section: "+ selectedElement.innerHTML + "</p>"; }
// update the content's title and main text var contentTitle =document.getElementById("content-title");
var contentValue =document.getElementById("content-value");
contentTitle.innerHTML =selectedElement.innerHTML;
contentValue.innerHTML = sectionData;}
演示(Demo)O'Reilly Mail或者下載(download)O'Reilly Mail的源代碼。
結束語
你現在已經學習了使用Really Simple History API 讓你的AJAX應用響應書簽和前進回退按鈕,而且有代碼可以作為創建你自己的應用的素材。我熱切地期待你利用書簽和歷史的支持完成你的AJAX創造。
原文轉自:http://www.anti-gravitydesign.com