譯文:
Master Pages 和 JavaScript document.getElementById
介紹
模板頁是ASP.NET 2.0的最重要的特性之一。但是,如果對於.NET2.0和模板頁是個新手的話,你需要在用javascript訪問內建於模板頁中的控制項這方面頗費點功夫了。每當一個控制項被置於模板頁中時,它的Client ID將會被修改。當Client ID修改後,在javascript中使用document.getElementById(serverID)
訪問這些控制項將不會奏效。在這篇文章中,我將討論一種比較簡單的方法獲得在javascript使用的模板頁中控制項的Client ID.
背景
當一個控制項在模板頁中時,這個控制項的Client ID將會被附著與他的Content placeholder ID.所以,如果一個元素的ID為txtTest”,那麼這個新的Client ID就會像"ctl00_ContentPlaceHolder1_ txtTest”.
所以,當你試著用document.getElementById(‘txtTest’)
, 你將無法使用javascript來訪問txtTest,你需要通過調用document.getElementById(‘ctl00_ContentPlaceHolder1_ txtTest’)來訪問它。
為了避免對這個較長的Client ID進行寫入程式碼,我們可以通過使用document.getElementById('<%=txtTest.ClientID%>')訪問控制項,這樣就能夠訪問txtTest.現在它將會奏效除非javascript與aspx也一致,也就是說,當javascript作為aspx頁的一部分時,這樣寫挺奏效的。但是如果把javascript語句放到單獨的.js檔案中通過指定路徑引用到aspx頁面的話,這樣寫就不行了。
所以,在這個指令碼裡,為了擷取控制項,我們不得不寫入程式碼控制項的ID,但是寫入程式碼不是編碼的理想方式,為了避免這種狀況,我們所能做的是在Client ID和Server ID間保持一個映射,在javascript代碼中,我們能夠根據給定的Server ID擷取Client ID,這個將在下面被實現。
使用這些編碼
在上面所說的將會在這裡實現,第一,我們需要申明兩個數組;第一個數組用來儲存控制項Server ID,第二個數組在同樣的位置存放伺服器控制項的Client ID.在用戶端註冊這兩個數組。現在,產生一個javascript的函數,接收server ID並且用這個server ID和數組中儲存的server ID進行比較,給出它在數組中的位置。然後,同樣的函數將會根據這個位置在Client ID數組中找到對應的Client ID.我感覺這是保持Client和Server IDs映射的最簡單的方法。
這段代碼顯示了數組的定義以及javascript的申明。
// This is the method used to register the array // of the clientid's as well as the serverid's // Also this method registers the function GetClientId, which is used// to get the client id provided server id is suppliedpublic void RenderJSArrayWithCliendIds(params Control[] wc){ if (wc.Length > 0) { StringBuilder arrClientIDValue = new StringBuilder(); StringBuilder arrServerIDValue = new StringBuilder(); // Get a ClientScriptManager reference from the Page class. ClientScriptManager cs = Page.ClientScript; // Now loop through the controls and build the client and server id's for (int i = 0; i < wc.Length; i++) { arrClientIDValue.Append("\"" + wc[i].ClientID + "\","); arrServerIDValue.Append("\"" + wc[i].ID + "\","); } // Register the array of client and server id to the client cs.RegisterArrayDeclaration("MyClientID", arrClientIDValue.ToString().Remove(arrClientIDValue.ToString().Length - 1, 1)); cs.RegisterArrayDeclaration("MyServerID", arrServerIDValue.ToString().Remove(arrServerIDValue.ToString().Length - 1, 1)); // Now register the method GetClientId, used to get the client id of tthe control cs.RegisterStartupScript(this.Page.GetType(), "key", "\nfunction GetClientId(serverId)\n{\nfor(i=0; i<MyServerID.length; i++)" + "\n{\nif ( MyServerID[i] == serverId )\n" + "{\nreturn MyClientID[i];\nbreak;\n}\n}\n}", true); } }
我們可以把這段代碼作為所有基UI頁面的公用類的一部分。這樣在每個頁面中需要通過javascript訪問控制項,我們可以把被訪問的控制項作為參數來調用這個函數。
//這裡我們需要把client ids 註冊到用戶端//以便能夠在javascript中使用同樣的//如果有多個控制項,用逗號隔開..RenderJSArrayWithCliendIds(txtTest);
這是得到Client和Server IDs映射的最簡單的方法。這裡,沒有必要擔心在外部javascript檔案中訪問模板頁中的控制項。
現在我們可以通過如下代碼訪問在javascript中被提交到RenderJSArrayWithCliendIds函數中的控制項。
var TextBox = document.getElementById(GetClientId("txtTest"));
這個將會解決由於控制項在模板頁中使得Client IDs改變而產生的任何問題。
原文
Introduction
Master Pages is one of the best features of ASP.NET 2.0. But, if you are a beginner in .NET 2.0 and Master Pages, you would get stuck in accessing controls placed inside a Master Page using JavaScript. Whenever a control is placed inside a Master Page, its client ID would be changed. As the client ID is changes, the document.getElementById(serverID)
of the control in JavaScript won't work. In this article, I will discuss about one of the simplest solutions to get the client ID of a control in a Master Page for use in JavaScript.
Background
Whenever a control is inside a Master Page, the client ID of the control would get appended with its content placeholder ID. So, for an element with an ID “txtTest
”, the new client ID would look something like “ctl00_ContentPlaceHolder1_ txtTest
”.
So, when you try to use document.getElementById(‘txtTest’)
, you will not get access to the txtTest
textbox in JavaScript. You need to access it by calling document.getElementById(‘ctl00_ContentPlaceHolder1_ txtTest’)
.
To avoid hard coding of very long client IDs, we can access the control by using document.getElementById('<%=txtTest.ClientID%>')
. This will give us access to txtTest
. Now, this will work fine until and unless the script is inline with the ASPX page, i.e., if the script is included as part of the ASPX page. But, the same won’t work if you have the script in a separate .js file and add it to the ASPX page by specifying its location.
So, in this scenario, to get access to the control, we have to hard code the control’s ID. But hard coding is not the ideal way of coding. To avoid this situation, what we can do is maintain a mapping between the client ID and the server ID. In the JavaScript code, we can get the client ID of the control by giving its server ID. This can be achieved as shown below.
Using the code
The above said can be achieved as shown here. First, we need to declare two arrays; the first array will have the server IDs of the required controls, and the second array will have the client IDs of the server controls in the same order. Register these two arrays at the client side. Now, create a JavaScript function which will accept the server ID and will compare the server ID with the available server IDs in the array and will give its position in the array. Then, the same function would return you the matching client ID from the same location in the client IDs array. I feel this is one of the simplest ways of maintaining a mapping between client and server IDs.
The code below shows the declaration of the array, and the declaration of the JavaScript function in the code-behind.
// This is the method used to register the array// of the clientid's as well as the serverid's // Also this method registers the function GetClientId, which is used// to get the client id provided server id is suppliedpublic void RenderJSArrayWithCliendIds(params Control[] wc){ if (wc.Length > 0) { StringBuilder arrClientIDValue = new StringBuilder(); StringBuilder arrServerIDValue = new StringBuilder(); // Get a ClientScriptManager reference from the Page class. ClientScriptManager cs = Page.ClientScript; // Now loop through the controls and build the client and server id's for (int i = 0; i < wc.Length; i++) { arrClientIDValue.Append("\"" + wc[i].ClientID + "\","); arrServerIDValue.Append("\"" + wc[i].ID + "\","); } // Register the array of client and server id to the client cs.RegisterArrayDeclaration("MyClientID", arrClientIDValue.ToString().Remove(arrClientIDValue.ToString().Length - 1, 1)); cs.RegisterArrayDeclaration("MyServerID", arrServerIDValue.ToString().Remove(arrServerIDValue.ToString().Length - 1, 1)); // Now register the method GetClientId, used to get the client id of tthe control cs.RegisterStartupScript(this.Page.GetType(), "key", "\nfunction GetClientId(serverId)\n{\nfor(i=0; i<MyServerID.length; i++)" + "\n{\nif ( MyServerID[i] == serverId )\n" + "{\nreturn MyClientID[i];\nbreak;\n}\n}\n}", true); } }
We can make this code a part of a common class for all UI pages like a page base, so that in every page we need to access a control in JavaScript, we can simply call the function with the control to be accessed as the parameter.
// Here we need to register the client ids to the client,// so that the same can be used in the javascript// If there are nultiple controls make it by comma seperated..RenderJSArrayWithCliendIds(txtTest);
This is one of the simplest ways to have a mapping between client and server IDs. Here, there is no need to worry about accessing a control inside a Master Page from an external JavaScript file.
Now, we can access the elements which are given in the RenderJSArrayWithCliendIds
function in the JavaScript as shown below:
var TextBox = document.getElementById(GetClientId("txtTest"));
This will solve any issue arising due to changes in the client IDs of controls placed inside a Master Page.