上方廣告

2012年7月2日 星期一

動態Included JavaScript的問題

在寫元件的時候常常會需要Included一些JavaScript檔,最近遇到一個問題就是需要Included一個jQuery檔案,但是NET所提供的【Page.ClientScript.RegisterClientScriptInclude】會把檔案放在<form></form>中間,這樣一來會有一些問題產生。

通常我們在寫JavaScript的時候,會習慣把JS寫在 <head><head>中間,如果頁面中有用到jQuery的話,必須要把jquery.x.x.js檔放在自己寫的JS上面,不然會發生找不到物件的情形產生。舉個例子來說,最近要寫一個在iframe載入完畢後要自動調整寬高,理論來說這麼簡單的語法,只需要透過JavaScript就可以輕易達成了(之前的文章也有提到),但最近發現先前所提到的寫法在不同瀏覽器計算出來的高度有誤,或者無法正常運作的情況產生,經過多次測試後發現,其實使用jQuery就可以輕易的取得我們所需要的iframe的寬高(測試幾個瀏覽器IE7,IE9,Chrome,Firefox都正常),於是我就想說寫一個IFrame的元件來用。
在寫元件的過程當中思考到兩個問題,一個就是剛剛所提到的Included檔會加到<form></form>之中,這不是我們所樂見的。另外一個就是就算我加到<head>當中了,那如果有一個頁面有兩顆元件都有用到jQuery會不會有衝突,先記住第二點問題就好,後面會再進行說明。

關於第一個問題其實NET本身有提供一個【HtmlGenericControl 類別】來讓我們定義HTML伺服器控制項,因此只要好好的運用此類別(別自己組字串了)。請參考以下語法。
System.Web.UI.HtmlControls.HtmlGenericControl headJS = new System.Web.UI.HtmlControls.HtmlGenericControl();
headJS.TagName = "script";
headJS.Attributes.Add("type", "text/javascript");
headJS.Attributes.Add("src", "jquery.js");//這裡的jquery.js請改成讀取Resource檔的資料來源
Page.Header.Controls.AddAt(0, headJS);


接下來要處理的就是第二個問題了,Page.ClientScript.RegisterClientScriptInclude本身有提供一個Key的識別項,如果我們透過RegisterClientScriptInclude來註冊JavaScript檔,我們可以很輕易的來辨識是不是有其它元件已經先加入此js檔了。但是為什麼不用,就如同上面所說的,會加到<form></form> 所以就只好放棄這麼好用的方法,因此我們必須自己檢查該JS檔是否已經被引用。稍微Google了一下人家有提到要自己檢查網頁中是不是已經存在相同src的JS檔,這樣就已經說明了問題解決了。因此自己寫一下檢查的Function套用一下問題就可以解決了,以下就是調整過後的語法。
if(!JsExist("jquery.js"))
{
 System.Web.UI.HtmlControls.HtmlGenericControl headJS = new System.Web.UI.HtmlControls.HtmlGenericControl();
 headJS.TagName = "script";
 headJS.Attributes.Add("type", "text/javascript");
 headJS.Attributes.Add("src", JsExist("jquery.js"));//這裡的jquery.js請改成讀取Resource檔的資料來源
 Page.Header.Controls.AddAt(0, headJS);
}
/// 判斷JS是否已加載
/// js url
private bool JsExist(string jsurl)
{
    bool resutl = false;
    ControlCollection objco = Page.Header.Controls;
    if (objco.Count > 0)
    {
        foreach (Control item in objco)
        {
            if (item.GetType() == typeof(System.Web.UI.HtmlControls.HtmlGenericControl))
            {
                System.Web.UI.HtmlControls.HtmlGenericControl objhgc = item as System.Web.UI.HtmlControls.HtmlGenericControl;
                if (objhgc.Attributes["src"].ToString() == jsurl)
                {
                    //JS已存在
                    resutl = true;
                }
            }
        }
    }
    return resutl;
}

如此一來我考慮到的兩個問題就都確認OK了。