今天為了做個選單,於是打算把 jQuery 放在 MasterPage 裡。如果網頁 (*.aspx) 和 MasterPage 放在同一層還 OK,但若程式和 MasterPage 分處不同的資料夾,就會因為相對路徑的問題而造成無法讀取 jQuery core 與 CSS。

嘗試做了幾個試驗,譬如說寫成這樣:
    <link type="text/css" href='<%=ResolveUrl("~/jquery/theme/ui.all.css") %>' rel="Stylesheet" />
或是這樣:
    <link type="text/css" href="<%=Request.ApplicationPath()%>/jquery/theme/ui.all.css"  rel="Stylesheet" />
這些方法都沒有用,不管我有沒有在 <head> 加上 runat="server"。前者會直接把整個單引號內的內容印出來,後者會出現「無法修改 Controls 集合,因為控制項包含程式碼區塊 (例如 <% ... %>)。」,都不是我要的結果啊。

最後在 Google 上找到這篇:"Moving jQuery File Reference to ASP.NET MasterPage",原來要先增加一個 ContentPlaceHolder。對方的範例是 for C# 的,像我用 VB 就是這樣做。

1. 在 MasterPage 的 *.master 檔裡,<head> 加上 runat="server" 屬性,並增加一個 ContentPlaceHolder。

    <head runat="server">       
        <asp:ContentPlaceHolder id="head" runat="server">
        </asp:ContentPlaceHolder>
 

        <script src="jquery/jquery-1.3.1.js" type="text/javascript"></script>  
    </head>

2. 一樣是 *.master 檔,把 script 或 css 加上 ResolveUrl 方法,使它們可以轉換為絕對路徑。

    <link type="text/css" href='<%#ResolveUrl("~/jquery/theme/ui.all.css") %>' rel="Stylesheet" />
    <script type="text/javascript" src='<%#ResolveUrl("~/jquery/jquery-1.3.1.js") %>'></script>

3. 在 *.master.vb 檔裡,覆寫原來的 OnLoad 方法。

    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        MyBase.OnLoad(e)
        Page.Header.DataBind()
    End Sub

 

原本打算如果真的不行就要動態註冊了,譬如說這樣:
    Me.PageScriptManager.RegisterClientScriptInclude("jQueryCore", "/jquery/jquery-1.3.1.js")

css 的部分就靠增加 head 的 Control 來處理:
    CSSLink.Href = "/jquery/theme/ui.all.css"
    CSSLink.Attributes("rel") = "stylesheet"
    CSSLink.Attributes("type") = "text/css"
    Me.Page.Header.Controls.Add(CSSLink)


不過後來沒用到,不曉得這樣會不會也有問題。




都弄好以後,開始寫程式,卻在某個套用 MasterPage 的頁面、使用 jQuery Impromptu 時,發生這樣的錯誤訊息:
  「Internet Explorer 無法開啟網際網路網站 http://....」
  (Internet Explorer cannot open the Internet site, Operation aborted)


因為其他套用 MasterPage 的頁面沒事,所以我很肯定是 content page 暴走了。原本猜測是在 content page 中不可以動態註冊 JavaScript、或是在 content page 不給動態註冊 jQuery,但是測試了以下的語法,都是可行的:
  ' 測試 JavaScript 可否動態註冊
  ScriptManager.RegisterStartupScript(Me, Me.GetType(), "jsalert", "alert('123');", True)
  ' 測試 jQuery 語法可否動態註冊
  ScriptManager.RegisterStartupScript(Me, Me.GetType(), "jqalert", "$('.myitem').text('123');", True)

既然最大的原因排除掉了,那嫌疑就落到 jQuery Impromptu 上面了。原本以為是這個 plug-in 有 Bug,但是找了很久都找不到相關的文件。後來拿錯誤訊息搜尋,剛好看到有人在 ExtJS 遇到一樣的問題,心想這幾個 library 感覺在跑的模式還滿像,就試著把 $(document).ready() 從 MasterPage 移掉、挪進 content page 裡動態註冊。
        Dim sb As StringBuilder = New StringBuilder
        sb.Append("$(document).ready(function() {" + vbCrLf)
        sb.Append("$.prompt('test')" + vbCrLf)
        sb.Append("});" + vbCrLf)
        ScriptManager.RegisterStartupScript(Me, Me.GetType(), "jsalert", sb.ToString(), True)


結果就好了,看來是 DOM 沒有載入完全我就召喚 Impromptu 出現的問題。 =_=#

原本設計時的想法是 $(document).ready() 要做的事是固定的,所以就把它放在 MasterPage 裡了。看來還得考慮到其他物件產生的時機點啊。

創作者介紹
創作者 fannys23 的頭像
fannys23

小攻城師的戰場筆記

fannys23 發表在 痞客邦 留言(6) 人氣()