因為搞了一整個早上,所以決定來好好整理一下這次的心得。
先來個前情提要好了。
我需要寫一個監控交易列表的網頁,內容就是一整排的交易明細,一段時間後會自動更新。
因為列表可能很長,櫃台在看某一筆資料的時候一定會捲動捲軸,
那如果在此時更新,通常Scrollbar會回到網頁Top的位置,這樣顯得很不方便。
所以我的需求是:自動更新的網頁,而且更新後Scrollbar會維持在更新前的位置。
這個目標在以前寫的版本已經有成功做到, 之前寫的網頁是一整個頁面,沒有框架。
要用Javascript refresh網頁有很多寫法,最常見的大概是:
window.location.reload(); 以及
window.location.href=self.location.href; 之類的。
而我當時試了許多方法,意外發現 window.history.go(int page) 可以達到我的目標。
history如字面意義是存放網頁的瀏覽紀錄。 變數page如果給1,就會有下一頁的效果;
同理給-1,就會回到上一頁。而要在本頁更新,則是傳0。
有趣的是它似乎把之前使用者瀏覽的最後位置也記住了,
所以不會有像用其他方法一樣Scrollbar又回到頁頂的問題。
所以之前的問題就這樣解決了。
不過現在重新寫過,要把介面改掉,切了四個框架。
現在我只要左上方的frame會更新就好,那要怎麼辦呢?
想說簡單,把window用frame取代掉就好啦!
window.top.frames[frame_name].location.reload();
這樣就可以只更新那個頁面了。
好,既然reload()可行,那麼history.go(0)應該也可以如法炮製吧?
window.top.frames[frame_name].history.go(0);
結果神奇的事情發生了:四個頁面全部一起Refresh了。
這不是很沒道理嗎?我有指定frame了呀!
不信邪的我又改了許多指定frame的方式:
parent.frame_name.history.go(0);
window.top.frame_name.history.go(0);
….
結果通通都沒用:四個頁面永遠會一起更新。
這樣不行啊!其他頁面還在做交易的時候隨便更新不就完蛋了?
我還一度以為history.go()對frame的執行有問題,所以另外開檔案測試了一下。
結果發現history.go(1)和history.go(-1)的運行都很正常:不會影響到別的frame。
單單只有傳0的時候會全部的frame一起動作…
心血來潮換了瀏覽器測,發現IE竟然Work得相當好!
這是什麼鬼設定我真的不明白了。
事情到此本來可以告一段落,因為店裡的Browser本來就是IE。
可是我還是希望能找到IE和FF都適用的方案,所以又花了些時間找方法。
這時候就是Google大賽了,以下是值得參考的幾項連結:
How to get an anchor after page being reloaded?
Maintain scrollbar position on postback
Auto-refresh dashboard/project grid
Maintaing Page Scroll Position
不過有很多方法都是從別的frame去控制另一個frame,
需要使用者的手動submit form之類的動作。
雖然理論上同一個頁面也可以用body onLoad的方法做到同樣的事情, 但是我老是試不成功。
本來想採用最後一條連結的方式,可是好像只有一開始試成功過,後來就不行了。
目前我還搞不清楚理由。好像接收不到onunload之後傳出去的訊息。
就算我把FF主控台說的錯誤訊息 => forms no properties 改掉,
把forms[0] 改成 form的名稱還是沒有辦法。
所以現在就先用Cookie的方式了(第三條連結下方,Michael Nacey的作法),
雖然我覺得用Cookie並不是個好作法,但是暫時就這樣做吧。
如果有人還發現了什麼好點子,請告訴我~
另外還要注意一點就是 body.onScroll() 和 scrollTop 在DTD版本不同的適用性。
現在的版本宣告已經不支援 body.onScroll() 了,所以要從JS裡面 Call window.scroll()。
至於取得頁面的scrollTop屬性,視宣告與IE版本不同有兩種寫法:
document.documentElement.scrollTop ( IE6, DTD 4.01 ) 或者是
document.body.scrollTop ( IE5, DTD 3.2 )
老實說,各家Browser在規格上的不一,真的是很煩!
下面附上Michael Nacey的JS code,有興趣的可以參考一下。
因為四個頁面的Cookie要分開存,所以我加了頁面的檔名到Cookie名稱前面。