此文章转载!
The Ever-Useful $get and $find ASP.NET AJAX Shortcut function

分类:ajax时间:2007-12-4 8:47:31作者:海浪
http://mattberseth.com/blog/2007/08/the_everuseful_get_and_find_as.html

If you have been working with Microsoft's ASP.NET AJAX components, you are probably very familiar with the $get and $find JavaScript shortcut functions.  If not, here is a quick refresher.

$get

Overview

$get can be used as shorthand for the document.getElementById and element.getElementById functions.  The $get shortcut function points to the Sys.UI.DomElement.getElementById JavaScript function which is defined as part of the ASP.NET AJAX client side library (which means you will need to include a ScriptManager on the page to be able to use it).  $get accepts two parameters, the first is the ID of the DOM element you want to retrieve, the second is the parent element of where the search starts.  The second parameter is optional and when it is not supplied defaults to the document element.  Here is the official API reference.

If you happen to step into $get during a debugging session you will find that it basically comes down to the following function ...

function get(id, element) {
//  validation code that was removed
if (!element) return document.getElementById(id);
if (element.getElementById) return element.getElementById(id);
//  manual DOM walk that was removed ...
}

Sample Usage 1

Here is a very simple sample page that contains a single line of text along with three buttons.  When you click on the buttons, the text changes color. 

    

The html for this page defines a JavaScript function that is wired to handle each of the button onclick events.  Inside the event handler, the $get shortcut is used to look up the div element that contains the text and set its color style to the appropriate color.  Here is the markup for this page ...

<form runat="server">
<asp:ScriptManager runat="server" />
<script type="text/javascript">
function changeColor(color){
//  fetch the div
var div = $get('div');
//  set the color to the provided value
div.style.color = color;
}
</script>
<div id="div">Some sample text.  You can change the color of the text by clicking the buttons</div>
<input id="btnBlue" type="button" value="Blue" onclick="changeColor('blue');" />
<input id="btnGreen" type="button" value="Green" onclick="changeColor('green');" />
<input id="btnRed" type="button" value="Red" onclick="changeColor('red');" />
</form>

While this example does show how $get can be used, it really isn't too useful since most ASP.NET web applications use server controls.  One thing we all have learned is that the ID assigned to the server control in the markup is not necessarily the same ID that is generated when the control is rendered.  No worries though, this can be overcome by using the ClientID property of the server control as the next sample demonstrates.

Sample Usage 2

For the second sample, we will update our sample page to use the Button and Label server controls instead of regular HTML elements.  Additionally, I am going to move the Label and Button controls into a ContentPage to further show why using the ClientID is required for the sample to work.  After adding the Buttons and Label to the page, I update the changeColor function to grab the ClientID value from the label like so ...

<asp:Content runat="server" ContentPlaceHolderID="ContentPlaceHolder1">
<asp:ScriptManager runat="server" />
<script type="text/javascript">
function changeColor(color){
//  fetch the div
var div = $get('<%= this.label.ClientID %>');
//  set the color to the provided value
div.style.color = color;
}
</script>
<asp:Label
ID="label" runat="server"
Text=
"Some sample text.  You can change the color of the text by clicking the buttons" />
<br />
<asp:Button
id="btnBlue" runat="server"
Text="Blue" OnClientClick="changeColor('blue');return false;" />
<asp:Button
id="btnGreen" runat="server"
Text="Green" OnClientClick="changeColor('green');return false;" />
<asp:Button
id="btnRed" runat="server"
Text="Red" OnClientClick="changeColor('red');return false;" />
</asp:Content>

Now if we view source for this page, you will notice that because the server controls are contained within a content page, the ID value I assigned the Label and Buttons has been prefixed with 'ctl00_ContentPlaceHolder1_'.  Below is what was actually sent to the browser.  Notice how all of the ID's are different from what we defined in the markup, but our JavaScript function still works since it was using the ClientID (the value was generated and output during the rendering process) ... 

<script type="text/javascript">
function changeColor(color){
//  fetch the div
var div = $get('ctl00_ContentPlaceHolder1_label');
//  set the color to the provided value
div.style.color = color;
}
</script>
<span id="ctl00_ContentPlaceHolder1_label">
Some sample text.  You can change the color of the text by clicking the buttons
</span>
<br />
<input
type="submit" name="ctl00$ContentPlaceHolder1$btnBlue"
value="Blue" onclick="changeColor('blue');return false;"
id="ctl00_ContentPlaceHolder1_btnBlue" />
<input
type="submit" name="ctl00$ContentPlaceHolder1$btnGreen"
value="Green" onclick="changeColor('green');return false;"
id="ctl00_ContentPlaceHolder1_btnGreen" />
<input
type="submit" name="ctl00$ContentPlaceHolder1$btnRed"
value="Red" onclick="changeColor('red');return false;"
id="ctl00_ContentPlaceHolder1_btnRed" />

 

If I would have tried to fetch the Label using the ID I assigned the control in the markup, it would not have found it and the page would not work properly.  While this example is a little bit more 'real world' than the original one, it really only works when you have access to the naming container the control (the Label in this case) you want to fetch resides in.  What if we wanted to change the text color of a row in a GridView based on the user clicking one of these three buttons?  Now that might actually be interesting ...

Sample Usage 3

So this brings us to our third sample usage.  In this example, I created a GridView with 2 columns.  Once for the text that we want to change the color of and the other containing the buttons.  To support this scenario I handle the GridView's RowDataBound event and set the OnClientClick property of the Buttons to invoke my changeColor JavaScript function, passing it the ClientID of the label (this ID will be different for every row) and the color that we want the text changed to.  Here is the screen shot of this grid and below that is the sample markup and code.  Notice that when I set the OnClientClick, I am using the ClientID property of the Label.

 

 
<asp:Content runat="server" ContentPlaceHolderID="ContentPlaceHolder1">
<asp:ScriptManager runat="server" />
<asp:ObjectDataSource
ID="odsCustomers" runat="server"
SelectMethod="Select" TypeName="CustomersDataObject" />
<script type="text/javascript">
function changeColor(labelID, color){
//  fetch the div
var div = $get(labelID);
//  set the color to the provided value
div.style.color = color;
}
</script>
<script runat="server">
/// <summary>
/// 
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
protected void GvText_RowDataBound(object sender, GridViewRowEventArgs args)
{
if (args.Row.RowType == DataControlRowType.DataRow)
{
//  get the controls from the row
Button btnBlue = (Button)args.Row.FindControl("btnBlue");
Button btnGreen = (Button)args.Row.FindControl("btnGreen");
Button btnRed = (Button)args.Row.FindControl("btnRed");
Label lblText = (Label)args.Row.FindControl("lblText");
const string onClientClick = "changeColor('{0}', '{1}'); return false;";
//  set the OnClientClick to call our JavaScript function
btnBlue.OnClientClick =
string.Format(onClientClick, lblText.ClientID, "blue");
btnGreen.OnClientClick =
string.Format(onClientClick, lblText.ClientID, "green");
btnRed.OnClientClick =
string.Format(onClientClick, lblText.ClientID, "red");
}
}
</script>
<asp:GridView
ID="gvText" runat="server" PageSize="5" AllowPaging="true"
DataSourceID="odsCustomers" AutoGenerateColumns="false"
OnRowDataBound="GvText_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Text">
<ItemTemplate>
<asp:Label
ID="lblText" runat="server"
Text=
"Some sample text.  You can change the ..." />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Colors">
<ItemTemplate>
<asp:Button id="btnBlue" runat="server" Text="Blue" />
<asp:Button id="btnGreen" runat="server" Text="Green" />
<asp:Button id="btnRed" runat="server" Text="Red" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:Content>

Thats it for the $get function, but before I move on to $find, I just wanted to point out a few items that I believe are minor documentation bugs with the asp.net/AJAX site related to the $get function ...

The documentation for $get reads ...

Provides a shortcut to the getElementById method, which returns an array of all components that have been registered with the application by using the addComponent method.

Is this second part correct?  Shouldn't this actually read ... Provides a shortcut to the getElementById method, which gets a DOM element that has the specified id attribute.

Also, the code sample for $get doesn't actually include using $get in the sample code. 

$find

 

Overview

The $find shortcut function allows you to look up an ASP.NET AJAX client side Component by it's ID.  Here is a link to the $find shortcut's documentation and below is the API description.

Use $find to Fetch an AjaxControlToolkit Extender Behavior

Many of the extender controls of the AjaxControlToolkit include a client side JavaScript API that allows your page to interact with the extender control from the client.  While the documentation on the toolkit is well above average, it focuses on the most common properties/attributes of the control and skims over the other less used properties/attributes as well as the client side API.  I have found the best way to learn about the client side API is to download the toolkit and browse the code. 

Once you discover the capabilities of an extender's the client side API, you are going to need to obtain a reference to the component so you can interact with it from your page.  All of the extender controls in the toolkit expose a property called BehaviorID (it is defined on the ExtenderControlBase so all toolkit controls inherit it by default).  You can set the BehaviorID in the controls markup, or you can leave it blank, in which case it will have the same ID of the control.  The 2 code samples below show both of these options.  In the first one, no BehaviorID is specified so this attribute takes on the same value as the ID.  In the second sample, I am explicitly specifying a BehaviorID of 'rceBehaviorID', so that is what I can use to look up the Component.

<%--
The behavior for this extender can be fetched using the following syntax:
var behavior = $find('rce1ID');
--%>
<ajaxToolkit:ResizableControlExtender ID="rce1ID" runat="server" ... />
<%--
The behavior for this extender can be fetched using the following syntax:
var behavior = $find('rceBehaviorID');
--%>
<ajaxToolkit:ResizableControlExtender ID="rce2ID" BehaviorID="rceBehaviorID" runat="server" ... />

Here is the JavaScript the ASP.NET AJAX runtime injects into the page to initialize these components.  Notice the value of the id attribute in the JSON:

 
<script type="text/javascript">
<!--
Sys.Application.initialize();
Sys.Application.add_init(function() {
$create(
AjaxControlToolkit.ResizableControlBehavior,
{
"ClientStateFieldID":"rce1ID_ClientState",
"HandleCssClass":"handleImage",
"id":"rce1ID"
        },
null, null, $get("pnl"));
});
Sys.Application.add_init(function() {
$create(
AjaxControlToolkit.ResizableControlBehavior,
{
"ClientStateFieldID":"rce2ID_ClientState",
"HandleCssClass":"handleImage",
"id":"rceBehaviorID"
},
null, null, $get("pnl"));
});
// -->
</script>

That's it.  Enjoy!

posted on 2008-02-28 11:46  snwsky  阅读(2765)  评论(0编辑  收藏  举报