2007/03/13

AJAX 上一頁問題

最近仍然在研究 PMC2 的框架發展,話說明明用想的就很簡單,用作的卻老是做不出來。也許該像捏黏土一樣,先捏出整個外觀再慢慢修細比較好吧,一直想把某一部份搞完美了才進行下一部分,莫怪乎進度一直快不起來。 (其實也沒有具體的時程表啦)

今日來談使用 AJAX 開發網路應用程式會發生的問題:上一頁問題。其實這個問題早被談爛了,而網路上也不少解決方案,但是我為啥還要搬出來談?我自己對所謂的 Framework 其實是不很能習慣,總覺得自己寫出來的東西才能最能貼近我的需要,也因此別人用 Prototype、 jQuery 幾步驟就完成的東西,我可能要搞很久才能實作出來。

回到「上一頁」問題。AJAX 即時取得遠端資料後,即排版利用 DOM 插入於網頁之中,但頁面內容已改變。假如此一改變是像回應模式、詳細列表一類的,當使用者看完後想回到之前的頁面,卻發現上一頁沒有辦法作用,導覽功能完全被打亂了,於是乎容易造成迷失的現象。另一個有點關聯的是這些回應模式、詳細列表需要以事件驅動,使用者無法直接連往某些位置就看到,可能需要再動動滑鼠點幾下才能看到他想要的結果,如果這些頁面能夠以一個唯一的 URL 資源連結,例如 index/list 可能就是詳細列表,這樣也能讓導覽功能變得較為親和。(延伸: Taiwan.CNET.com AJAX的七項致命原罪)

一個好的 AJAX Web Application 應該要讓使用者以習慣的導覽功能來使用,所以這還是不可忽視。目前解決「上一頁」問題的方法已大致底定,統整後歸納如下:

視瀏覽器而定,像 IE 就需要另外一個 iframe 來幫助記憶瀏覽記錄,而使瀏覽器的瀏覽記錄能夠被我們所控制的關鍵是錨點 (document.location.hash) 值,這個值一旦變動,瀏覽器的瀏覽記錄便會增加記錄。但這在 IE 是例外,但如果以 iframe 輔助並改變其內頁面的 Hash 值,瀏覽器的記錄又有用了。

能操作瀏覽紀錄後,接著我們需要模擬一個 window.onback() (目前瀏覽器當然沒有這個事件,希望日後有) 偵測是否按下上一頁按鈕。很遺憾的前面說過目前沒有按下上一頁按鍵事件可以用,而頁面的 onload 又只適用於初次載入 (也就是說後續使用 DOM 修改頁面、更動 Hash 值都不會再觸發 onload 事件)。所以我們需要設一個 Listener,定期偵測瀏覽記錄記載的的 Hash 改了沒。可用的方法就是 setInterval 定期執行檢查 (例如每 100 毫秒),當瀏覽記錄的 Hash 變了 (比方說從 index.htm => index.htm#list) 就是 window.onback() 模擬事件的執行時機。

最後,在我們做的這個 onback 事件被驅動之時,需要作一個控制函式,利用目前頁面的 Hash 完成某些特定動作。例如上面的 index.htm -> index.htm#list,抓取目前的 document.location.hash (=#list),並執行對應的動作 (如 JavaScript: GetList()),這樣不但可以模擬出上一頁效果,也可以利用 index.htm#list 這個 URL 資源直接連結到顯示詳細列表的功能了。

要說一下的是,最後提到的控制函式類似中央集權,所有的 AJAX 相關操作通通給他掌權,那觸動的超連結或按鈕只需想辦法改變瀏覽記錄的 Hash 即可 (直接連結至錨點 / 修改 iframe 錨點),例如 <a href="#list" rel="ajaxlink" onclick="setHistory(this.href.replace(/^.*#/, ''));"> List </a>。如果嫌每個連結都要加入修改 iframe Hash 事件太煩,可以利用 window.onload 搭配超連結尋找特定 rel 值標記來辨識各連結物件並動態增加 onclick 事件。

值得一提的是以往的舊方法需要 iframe 連結至一個 blank.htm 並傳遞參數以記錄相關資訊,現在的做法多直接把 iframe 當成一個畫布般,對其初始化後直接修改頁面 Hash。方法如下:


var iframe = document.getElementById('ieHistory').contentWindow.document;
iframe.open(); iframe.close();


只需開啟文件後再關閉即達成初始化動作,就可以當作一般網頁自由修改 Hash 值而不必再用一個頁面來模擬。
---
最後,我嘗試一下 jQuery.history 的功能,幫這個頁面的回應模式加上了上一頁模擬,如果你按了[回應]觀看文章全文及回應後,可以再按瀏覽器上一頁回到文章瀏覽模式。

2 則留言:

  1. 先生!問題があります!
    如果是forward或是hash plink呢?

    回覆刪除
  2. >>forward
    其實一併解決,因為我們掌握 Hash / iframe 為新的瀏覽歷史,而瀏覽器也能將其掌握的很好。
    所以說那個 window.onback 應該說成 window.onHashchange 才對。

    用 Hash 作Permanent Link的話,利用上面的 window.onback (onHashchange) 事件來做就可以了。
    第一次進入時也會將 Hash 交給控制函式。(所以 Hash 空的也會觸發,看你要不要用而已)

    回覆刪除