今天為了做個選單,於是打算把 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 裡了。看來還得考慮到其他物件產生的時機點啊。
留言列表