<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 66,  comments - 40,  trackbacks - 0
    ?
    用AJAX來(lái)控制書(shū)簽和回退按鈕

    作者:Brad Neuberg

    譯者:boool


    版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
    作者:Brad Neuberg;boool
    原文地址:http://www.onjava.com/pub/a/onjava/2005/10/26/ajax-handling-bookmarks-and-back-button.html
    中文地址:http://www.matrix.org.cn/resource/article/43/43972_AJAX.html
    關(guān)鍵詞: ajax;bookmarks;back button


    這篇文章描述了一個(gè)支持AJAX應(yīng)用書(shū)簽和回退按鈕的開(kāi)源的javascript庫(kù)。在這個(gè)指南的最后,開(kāi)發(fā)者將會(huì)得出一個(gè)甚至不是Google Maps 或者 Gmail那樣處理的AJAX的解決方案:健壯的,可用的書(shū)簽和向前向后的動(dòng)作能夠象其他的web頁(yè)面一樣正確的工作。

    AJAX:怎樣去控制書(shū)簽和回退按鈕 這篇文章說(shuō)明了一個(gè)重要的成果,AJAX應(yīng)用目前面對(duì)著書(shū)簽和回退按鈕的應(yīng)用,描述了非常簡(jiǎn)單的歷史庫(kù)(Really Simple History),一個(gè)開(kāi)源的解決這類(lèi)問(wèn)題的框架,并提供了一些能夠運(yùn)行的例子。

    這篇文章描述的主要問(wèn)題是雙重的,一是一個(gè)隱藏的html 表單被用作一個(gè)大而短生命周期的客戶(hù)端信息的session緩存,這個(gè)緩存對(duì)在這個(gè)頁(yè)面上前進(jìn)回退是強(qiáng)壯的。二是一個(gè)錨連接和隱藏的iframes的組合用來(lái)截取和記錄瀏覽器的歷史事件,來(lái)實(shí)現(xiàn)前進(jìn)和回退的按鈕。這兩個(gè)技術(shù)都被用一個(gè)簡(jiǎn)單的javascript庫(kù)來(lái)封裝,以利于開(kāi)發(fā)者的使用。

    存在的問(wèn)題
    書(shū)簽和回退按鈕在傳統(tǒng)的多頁(yè)面的web應(yīng)用上能順利的運(yùn)行。當(dāng)用戶(hù)在網(wǎng)站上沖浪時(shí),他們的瀏覽器地址欄能更新URL,這些URL可以被粘貼到的email或者添加到書(shū)簽以備以后的使用。回退和前進(jìn)按鈕也可以正常運(yùn)行,這可以使用戶(hù)在他們?cè)L問(wèn)的頁(yè)面間移動(dòng)。

    AJAX應(yīng)用是與眾不同的,然而,他也是在單一web頁(yè)面上成熟的程序。瀏覽器不是為AJAX而做的—AJAX他捕獲過(guò)去的事件,當(dāng)web應(yīng)用在每個(gè)鼠標(biāo)點(diǎn)擊時(shí)刷新頁(yè)面。

    在象Gmail那樣的AJAX軟件里,瀏覽器的地址欄正確的停留就象用戶(hù)在選擇和改變應(yīng)用的狀態(tài)時(shí),這使得作書(shū)簽到特定的應(yīng)用視圖里變得不可能。此外,如果用戶(hù)按下了他們的回退按鈕去返回上一個(gè)操作,他們會(huì)驚奇的發(fā)現(xiàn)瀏覽器將完全離開(kāi)原來(lái)他所在的應(yīng)用的web頁(yè)面。

    解決方案
    開(kāi)源的Really Simply History(RSH)框架解決了這些問(wèn)題,他帶來(lái)了AJAX應(yīng)用的作書(shū)簽和控制前進(jìn)后退按鈕的功能。RSH目前還是beta版,在Firefox1.0上,Netscape7及以上,和IE6及以上運(yùn)行。Safari現(xiàn)在還不支持(要得到更詳細(xì)的說(shuō)明,請(qǐng)看我的weblog中的文章Coding in Paradise: Safari: No DHTML History Possible).

    目前存在的幾個(gè)AJAX框架可以幫助我們做書(shū)簽和發(fā)布?xì)v史,然而所有的框架都因?yàn)樗麄兊膶?shí)現(xiàn)而被幾個(gè)重要的bug困擾(請(qǐng)看Coding in Paradise: AJAX History Libraries 得知詳情)。此外,許多AJAX歷史框架集成綁定到較大的庫(kù)上,比如Backbase 和 Dojo,這些框架提供了與傳統(tǒng)AJAX應(yīng)用不同的編程模型,強(qiáng)迫開(kāi)發(fā)者去采用一整套全新的方式去獲得瀏覽器的歷史相關(guān)的功能。

    相應(yīng)的,RSH是一個(gè)簡(jiǎn)單的模型,能被包含在已經(jīng)存在的AJAX系統(tǒng)中。而且,Really Simple History庫(kù)使用了一些技巧去避免影響到其他歷史框架的bug.

    Really Simple History框架由2個(gè)javascript類(lèi)庫(kù)組成,分別叫DhtmlHistory 和 HistoryStorage.

    DhtmlHistory 類(lèi)提供了一個(gè)對(duì)AJAX應(yīng)用提取歷史的功能。.AJAX頁(yè)面add() 歷史事件到瀏覽器里,指定新的地址和關(guān)聯(lián)歷史數(shù)據(jù)。DhtmlHistory 類(lèi)用一個(gè)錨的hash表更新瀏覽器現(xiàn)在的URL,比如#new-location ,然后用這個(gè)新的URL關(guān)聯(lián)歷史數(shù)據(jù)。AJAX應(yīng)用注冊(cè)他們自己到歷史監(jiān)聽(tīng)器里,然后當(dāng)用戶(hù)用前進(jìn)和后退按鈕導(dǎo)航的時(shí)候,歷史事件被激發(fā),提供給瀏覽器新的地址和調(diào)用add()持續(xù)保留數(shù)據(jù)。

    第二個(gè)類(lèi)HistoryStorage,允許開(kāi)發(fā)者存儲(chǔ)任意大小的歷史數(shù)據(jù)。一般的頁(yè)面,當(dāng)一個(gè)用戶(hù)導(dǎo)航到一個(gè)新的網(wǎng)站,瀏覽器會(huì)卸載和清除所有這個(gè)頁(yè)面的應(yīng)用和javascript狀態(tài)信息。如果用戶(hù)用回退按鈕返回過(guò)來(lái)了,所有的數(shù)據(jù)已經(jīng)丟失了。HistoryStorage 類(lèi)解決了這個(gè)問(wèn)題,他有一個(gè)api 包含簡(jiǎn)單的hashtable方法比如put(),get(),hasKey()。這些方法允許開(kāi)發(fā)者在離開(kāi)web頁(yè)面時(shí)存儲(chǔ)任意大小的數(shù)據(jù),當(dāng)用戶(hù)點(diǎn)了回退按鈕返回時(shí),數(shù)據(jù)可以通過(guò)HistoryStorage 類(lèi)被訪問(wèn)。我們通過(guò)一個(gè)隱藏的表單域(a hidden form field),利用瀏覽器即使在用戶(hù)離開(kāi)web頁(yè)面也會(huì)自動(dòng)保存表單域值的這個(gè)特性,完成這個(gè)功能。

    讓我們立即進(jìn)入一個(gè)簡(jiǎn)單的例子吧。

    示例1
    首先,任何一個(gè)想使用Really Simple History框架的頁(yè)面必須包含(include)dhtmlHistory.js 腳本。

    <!-- Load the Really Simple 
    ???? History framework -->
    <script type="text/javascript"
    ????????src="../../framework/dhtmlHistory.js">
    </script>


    DHTML History 應(yīng)用也必須在和AJAX web頁(yè)面相同的目錄下包含一個(gè)叫blank.html 的指定文件,這個(gè)文件被Really Simple History框架綁定而且對(duì)IE來(lái)說(shuō)是必需的。另一方面,RSH使用一個(gè)hidden iframe 來(lái)追蹤和加入IE歷史的改變,為了正確的執(zhí)行功能,這個(gè)iframe需要指向一個(gè)真正的地址,不需要blank.html。

    RSH框架創(chuàng)建了一個(gè)叫dhtmlHistory 的全局對(duì)象,作為操作瀏覽器歷史的入口。使用dhtmlHistory 的第一步需要在頁(yè)面加載后初始化這個(gè)對(duì)象。

    window.onload = initialize;
    ????
    function initialize() {
    ??// initialize the DHTML History
    ??// framework
    ??dhtmlHistory.initialize();


    然后,開(kāi)發(fā)者使用dhtmlHistory.addListener()方法去訂閱歷史改變事件。這個(gè)方法獲取一個(gè)javascript回調(diào)方法,當(dāng)一個(gè)DHTML歷史改變事件發(fā)生時(shí)他將收到2個(gè)自變量,新的頁(yè)面地址,和任何可選的而且可以被關(guān)聯(lián)到這個(gè)事件的歷史數(shù)據(jù)。

    indow.onload = initialize;
    ????
    function initialize() {
    ??// initialize the DHTML History
    ??// framework
    ??dhtmlHistory.initialize();
    ??
    ??// subscribe to DHTML history change
    ??// events
    ??dhtmlHistory.addListener(historyChange);


    historyChange()方法是簡(jiǎn)單易懂得,它是由一個(gè)用戶(hù)導(dǎo)航到一個(gè)新地址后收到的新地址(newLocation)和一個(gè)關(guān)聯(lián)到事件的可選的歷史數(shù)據(jù)historyData 構(gòu)成的。

    /** Our callback to receive history change
    ???? events. */
    function historyChange(newLocation,
    ?????????????????????? historyData) {
    ??debug("A history change has occurred: "
    ????????+ "newLocation="+newLocation
    ????????+ ", historyData="+historyData,
    ????????true);
    }


    上面用到的debug()方法是例子代碼中定義的一個(gè)工具函數(shù),在完整的下載例子里有。debug()方法簡(jiǎn)單的在web頁(yè)面上打一條消息,第2個(gè)Boolean變量,在代碼里是true,控制一個(gè)新的debug消息打印前是否要清除以前存在的所有消息。

    一個(gè)開(kāi)發(fā)者使用add()方法加入歷史事件。加入一個(gè)歷史事件包括根據(jù)歷史的改變指定一個(gè)新的地址,就像"edit:SomePage"標(biāo)記, 還提供一個(gè)事件發(fā)生時(shí)可選的會(huì)被存儲(chǔ)到歷史數(shù)據(jù)historyData值.

    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);


    在add()方法被調(diào)用后,新地址立刻被作為一個(gè)錨值顯示在用戶(hù)的瀏覽器的URL欄里。例如,一個(gè)AJAX web頁(yè)面停留在http://codinginparadise.org/my_ajax_app,調(diào)用了dhtmlHistory.add("helloworld", "Hello World Data" 后,用戶(hù)將在瀏覽器的URL欄里看到下面的地址
    http://codinginparadise.org/my_ajax_app#helloworld

    然后他們可以把這個(gè)頁(yè)面做成書(shū)簽,如果他們使用這個(gè)書(shū)簽,你的AJAX應(yīng)用可以讀出#helloworld值然后使用她去初始化web頁(yè)面。Hash里的地址值被Really Simple History??框架顯式的編碼和解碼(URL encoded and decoded) (這是為了解決字符的編碼問(wèn)題)

    對(duì)當(dāng)AJAX地址改變時(shí)保存更多的復(fù)雜的狀態(tài)來(lái)說(shuō),historyData??比一個(gè)更容易的匹配一個(gè)URL的東西更有用。他是一個(gè)可選的值,可以是任何javascript類(lèi)型,比如Number, String, 或者 Object 類(lèi)型。有一個(gè)例子是用這個(gè)在一個(gè)多文本編輯器(rich text editor)保存所有的文本,例如,如果用戶(hù)從這個(gè)頁(yè)面漂移(或者說(shuō)從這個(gè)頁(yè)面導(dǎo)航到其他頁(yè)面,離開(kāi)了這個(gè)頁(yè)面)走。當(dāng)一個(gè)用戶(hù)再回到這個(gè)地址,瀏覽器會(huì)把這個(gè)對(duì)象返回給歷史改變偵聽(tīng)器(history change listener)。

    開(kāi)發(fā)者可以提供一個(gè)完全的historyData 的javascript對(duì)象,用嵌套的對(duì)象objects和排列arrays來(lái)描繪復(fù)雜的狀態(tài)。只要是JSON (JavaScript Object Notation)??允許的那么在歷史數(shù)據(jù)里就是允許的,包括簡(jiǎn)單數(shù)據(jù)類(lèi)型和null型。DOM的對(duì)象和可編程的瀏覽器對(duì)象比如XMLHttpRequest ,不會(huì)被保存。注意historyData 不會(huì)被書(shū)簽持久化,如果瀏覽器關(guān)掉,或者瀏覽器的緩存被清空,或者用戶(hù)清除歷史的時(shí)候,會(huì)消失掉。

    使用dhtmlHistory 最后一步,是isFirstLoad() 方法。如果你導(dǎo)航到一個(gè)web頁(yè)面,再跳到一個(gè)不同的頁(yè)面,然后按下回退按鈕返回起始的網(wǎng)站,第一頁(yè)將完全重新裝載,并激發(fā)onload事件。這樣能產(chǎn)生破壞性,當(dāng)代碼在第一次裝載時(shí)想要用某種方式初始化頁(yè)面的時(shí)候,不會(huì)再刷新頁(yè)面。isFirstLoad() 方法讓區(qū)別是最開(kāi)始第一次裝載頁(yè)面,還是相對(duì)的,在用戶(hù)導(dǎo)航回到他自己的瀏覽器歷史中記錄的網(wǎng)頁(yè)時(shí)激發(fā)load事件,成為可能。

    在例子代碼中,我們只想在第一次頁(yè)面裝載的時(shí)候加入歷史事件,如果用戶(hù)在第一次裝載后,按回退按鈕返回頁(yè)面,我們就不想重新加入任何歷史事件。

    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);


    讓我們繼續(xù)使用historyStorage 類(lèi)。類(lèi)似dhtmlHistory ,historyStorage通過(guò)一個(gè)叫historyStorage的單一全局對(duì)象來(lái)顯示他的功能,這個(gè)對(duì)象有幾個(gè)方法來(lái)偽裝成一個(gè)hash table, 象put(keyName, keyValue), get(keyName), and hasKey(keyName).鍵名必須是字符,同時(shí)鍵值可以是復(fù)雜的javascript對(duì)象或者甚至是xml格式的字符。在我們?cè)创asource code的例子中,我們put() 簡(jiǎn)單的XML??到historyStorage 在頁(yè)面第一次裝載時(shí)。

    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);
    ??}


    然后,如果用戶(hù)從這個(gè)頁(yè)面漂移走(導(dǎo)航走)又通過(guò)返回按鈕返回了,我們可以用get()提出我們存儲(chǔ)的值或者用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() 是一個(gè)第一在例子源碼full example source code中的工具方法。這個(gè)方法準(zhǔn)備簡(jiǎn)單的xml顯示在web page ,方便調(diào)試。

    注意數(shù)據(jù)只是在使用頁(yè)面的歷史時(shí)被持久化,如果瀏覽器關(guān)閉了,或者用戶(hù)打開(kāi)一個(gè)新的窗口又再次鍵入了ajax應(yīng)用的地址,歷史數(shù)據(jù)對(duì)這些新的web頁(yè)面是不可用的。歷史數(shù)據(jù)只有在用前進(jìn)或回退按鈕時(shí)才被持久化,而且在用戶(hù)關(guān)閉瀏覽器或清空緩存的時(shí)候會(huì)消失掉。想真正的長(zhǎng)時(shí)間的持久化,請(qǐng)看Ajax MAssive Storage System (AMASS).
    我們的簡(jiǎn)單示例已經(jīng)完成。演示他(Demo it)或者下載全部的源代碼(download the full source code.)

    示例2
    我們的第2個(gè)例子是一個(gè)簡(jiǎn)單的模擬ajax email??應(yīng)用的示例,叫O'Reilly Mail,類(lèi)似Gmail. O'Reilly Mail描述了怎樣使用dhtmlHistory類(lèi)去控制瀏覽器的歷史,和怎樣使用historyStorage對(duì)象去緩存歷史數(shù)據(jù)。

    O'Reilly Mail 用戶(hù)接口(user interface)有兩部分。在頁(yè)面的左邊是一個(gè)有不同email文件夾和選項(xiàng)的菜單,例如 收件箱,草稿,等等。當(dāng)一個(gè)用戶(hù)選擇了一個(gè)菜單項(xiàng),比如收件箱,我們用這個(gè)菜單項(xiàng)的內(nèi)容更新右邊的頁(yè)面。在一個(gè)實(shí)際應(yīng)用中,我們會(huì)遠(yuǎn)程取得和顯示選擇的信箱內(nèi)容,不過(guò)在O'Reilly Mail里,我們簡(jiǎn)單的顯示選擇的選項(xiàng)。

    O'Reilly Mail使用Really Simple History 框架向?yàn)g覽器歷史里加入菜單變化和更新地址欄,允許用戶(hù)利用瀏覽器的回退和前進(jìn)按鈕對(duì)應(yīng)用做書(shū)簽和跳到上一個(gè)變化的菜單。

    我們加入一個(gè)特別的菜單項(xiàng),地址簿,來(lái)描繪historyStorage 能夠怎樣被使用。地址簿是一個(gè)由聯(lián)系的名字電子郵件和地址組成的javascript數(shù)組,在一個(gè)真實(shí)的應(yīng)用里我們會(huì)取得他從一個(gè)遠(yuǎn)程的服務(wù)器。不過(guò),在O'Reilly Mail里,我們?cè)诒镜貏?chuàng)建這個(gè)數(shù)組,加入幾個(gè)名字電子郵件和地址,然后把他們存儲(chǔ)在historyStorage 對(duì)象里。如果用戶(hù)離開(kāi)了這個(gè)web頁(yè)面以后又返回的話,O'Reilly Mail應(yīng)用重新從緩存里得到地址簿,勝過(guò)(不得不)再次訪問(wèn)遠(yuǎn)程服務(wù)器。

    地址簿是在我們的初始化initialize()方法里存儲(chǔ)和重新取得的

    /** 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 button
    ??????historyStorage.put("addressBook",
    ???????????????????????? addressBook);
    ?? }
    ?? else {
    ??????// fetch the cached address book from
    ??????// the history storage
    ??????window.addressBook =
    ?????????????? historyStorage.get("addressBook");
    ?? }


    處理歷史變化的代碼是簡(jiǎn)單的。在下面的代碼中,當(dāng)用戶(hù)不論按下回退還是前進(jìn)按鈕handleHistoryChange 都被調(diào)用。我們得到新的地址(newLocation) 使用他更新我們的用戶(hù)接口來(lái)改變狀態(tài),通過(guò)使用一個(gè)叫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的源代碼。

    結(jié)束語(yǔ)
    你現(xiàn)在已經(jīng)學(xué)習(xí)了使用Really Simple History API 讓你的AJAX應(yīng)用響應(yīng)書(shū)簽和前進(jìn)回退按鈕,而且有代碼可以作為創(chuàng)建你自己的應(yīng)用的素材。我熱切地期待你利用書(shū)簽和歷史的支持完成你的AJAX創(chuàng)造。

    資源
    ·onjava.com:onjava.com
    ·Matrix-Java開(kāi)發(fā)者社區(qū):http://www.matrix.org.cn/
    ·Download all sample code for this article.
    ·Download the Really Simple History framework.
    ·Demo O'Reilly Mail or download the O'Reilly Mail source code. The full example download also includes more examples for you to play with.
    ·Coding in Paradise: The author's weblog, covering AJAX, DHTML, and Java techniques and new developments in collaborative technologies, such as WikiWikis.


    感謝
    特別的要感謝每個(gè)檢閱這篇文章的the Really Simple History框架的人:
    Michael Eakes, Jeremy Sevareid, David Barrett, Brendon Wilson, Dylan Parker, Erik Arvidsson, Alex Russell, Adam Fisk, Alex Lynch, Joseph Hoang Do, Richard MacManus, Garret Wilson, Ray Baxter, Chris Messina, and David Weekly.
    posted on 2006-05-08 11:52 happytian 閱讀(341) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    Welcome here, my friend!

    常用鏈接

    留言簿(12)

    隨筆檔案(66)

    文章分類(lèi)

    文章檔案(63)

    web

    最新隨筆

    搜索

    •  

    積分與排名

    • 積分 - 89206
    • 排名 - 647

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 好吊妞视频免费视频| 精品一区二区三区无码免费视频| 无码精品人妻一区二区三区免费| v片免费在线观看| 18禁在线无遮挡免费观看网站| 毛片无码免费无码播放| 特级做A爰片毛片免费69| 国产色爽免费视频| 亚洲桃色AV无码| 亚洲美女在线观看播放| 亚洲色大成网站www| 国产精品99爱免费视频| 中文字幕免费高清视频| 日本高清免费aaaaa大片视频| 精品国产日韩亚洲一区| 久久久国产精品亚洲一区| 亚洲天堂免费在线| 一级毛片aaaaaa视频免费看| 免费播放一区二区三区| 日韩高清在线高清免费| 国产亚洲婷婷香蕉久久精品| 亚洲人成网男女大片在线播放| 成人特级毛片69免费观看| 一区二区三区四区免费视频 | 国产区图片区小说区亚洲区| 国产午夜精品理论片免费观看| 黄色网址免费观看| 亚洲国产天堂久久综合| 亚洲小说区图片区| 一进一出60分钟免费视频| 免费看片在线观看| 久久综合亚洲色HEZYO国产| 亚洲一区二区三区免费观看| yellow视频免费在线观看| 91精品免费国产高清在线| 国产啪亚洲国产精品无码| 国产成人精品日本亚洲网址| 中国好声音第二季免费播放| 妞干网手机免费视频| 亚洲高清视频在线观看| 麻豆安全免费网址入口|