使用JSCookMenu碰到的小問題
Wed, 06 Jun 2007 16:03:05 +0800JSCookMenu是一個相當容易用的JavaScript Base選單程式,可以很簡單地用陣列來製作選單,支援不同的佈景主題,作者也持續有在更新(目前最新版本到2.0.3)。
作者的網頁裡面有詳細的說明:http://jscook.yuanheng.org/JSCookMenu/
最近使用上卻遇到一點小問題,就是選單有時會失靈....花了一些時間嘗試,發現了一點小問題,問題發生在防毒軟體、瀏覽器toolbar上面的攔阻彈出視窗功能。
JSCookMenu用cmItemMouseUp函數來處理mouseup動作,click之後的處理也是用到這一個函數。這個函數中處理link的方法大致如下:
if (link != null) { _cmClicked = false; window.open (link, target); }
Symantec Internet Security 2006(我的筆記本預裝的防毒軟體)會在網頁中自動加上一段JavaScript,用來攔截彈出視窗:
function SymError() { return true; } window.onerror = SymError; var SymRealWinOpen = window.open; function SymWinOpen(url, name, attributes) { return (new Object()); } window.open = SymWinOpen;
結果就是window.open被攔截了,當然無法使用。先嘗試用幾個方法來對付,在firefox下global scope的變數會放在window物件中,所以可以用這樣的方法來試探究竟window.open被改到哪裡去了(不直接使用SymRealWinOpen變數,是因為希望對所有用這個方法封鎖彈出視窗的方式都可用),然後再把他改回來:
for (obj in window) { str1 = ""; str1 += obj; str2 = ""; str2 += window[str1]; if (str2.indexOf("function open()")>-1) { //懶得用re,先用indexOf比較快 window.open = window[str1]; } }
很可惜,這個方法在ie7裡面沒有作用....似乎ie7的javascript引擎並沒有把global scope的變數放在window物件中....(沒仔細測試,但是至少用firefox可行的方法出不來)
後來試用了一下google toolbar,發現他根本不依靠javascrpt來攔阻彈出視窗,所以即使用window.open=SymRealWinOpen也沒用,照樣攔截。這樣JSCookMenu就會有問題了....
袁衡的JSCookMenu支援可以在click選單時依照target指定的目標來開啟連結,通常的應用是指定"_self"來在原來的網頁視窗開啟,指定"_blank"開啟新視窗,指定其他的目標(frame、iframe等等)則會在相應的目標開啟。光用window.location.href=link沒辦法支援這麼多應用。
後來想到一個方法理論上可以兩全其美(還是有缺點,後面會提到),就是form。因為form一樣有target屬性,可以利用這個方法來彈出新視窗也不會被攔阻。我稍微改了一下JSCookMenu的程式:
if (link != null) { _cmClicked = false; tmp = document.createElement("form"); //動態產生form物件 tmp.target = target; tmp.method = "post"; //用post方法網址尾巴才不會出現? tmp.action = link; document.body.appendChild(tmp); tmp.submit(); //送出post document.body.removeChild(tmp); delete tmp; //form不用了,把他移除 }
試了一下,果然可以動了。不過因為是用post,連結的網頁必須避免錯誤處理這個post,另外有一些網站還是可能用referer來攔阻不恰當來源的post,也有可能有問題。我在寫的東西全部在自己網頁裡,就不需要擔心了:D
另外需要考慮的是動態改動node tree其實是會給瀏覽器帶來一些額外的負擔,比較起來用window.location.href=link速度的確快了一些。不過因為原本的目的就是要跳到不同的網頁或是開啟新視窗,所以這樣的延遲就比較不要緊了。
其實並沒有測試過所有的彈出視窗攔阻程式,所以不一定都可以通過啦。我還有注意到,用滑鼠右鍵點JSCookMenu選單時,會被google toolbar攔截.....不過用左鍵點選沒問題。感覺google toolbar攔阻的policy似乎必須用滑鼠左鑑,並且用form來開新視窗才能通過的樣子。