ForrestLedbetter.com Rotating Header Image

Javascript

Name Mangling, Solution 2

Here is a much cleaner solution. Instead of having to modify all of your javascript calls to use a new function to get elements by partial id or name, you can put a recursive function in the Master Pages onload, which will walk through all the controls and create a javascript variable named with the controls original name, which points to the object declared by the new name. As long as you don’t use any special characters in your elements ids/names, this works like a charm.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace TestPage
{
public partial class TestPage : System.Web.UI.MasterPage
{
System.Text.StringBuilder strControls = new System.Text.StringBuilder();
protected void Page_Load(object sender, EventArgs e)
{
controlWalker(this.Page);
Page.ClientScript.RegisterStartupScript(this.GetType(), “ctrl_ids”, strControls.ToString(), true);
}
private void controlWalker(Control ctrl)
{
if (ctrl.HasControls())
{
foreach (Control ctrl2 in ctrl.Controls)
{
controlWalker(ctrl2);
}
}
else
{
string sClientId = ctrl.ClientID;
string sOriginalId = ctrl.ID;
strControls.Append(“var “);
strControls.Append(sOriginalId);
strControls.Append(“=document.getElementById(‘”);
strControls.Append(sClientId);
strControls.Append(“‘);”);
}
}
}
}

Name Mangling, Solution 1

UPDATE:
NEVER DO THIS! This is a horrible suggestion, and should never be attempted by any sane person. I know, I know…I wrote it. I should delete it, but no… This is just another step in my learning process. If you take anything from this post, view it as what NOT to do.

ASP.Net’s implementation of master pages can wreak havoc on older applications during the conversion process. For instance, consider your old javascript that manipulates or validates page controls based on the control’s id. Well, when the rendering engine applies your content pages to the master pages, all elements in the content page will be renamed to a fully qualified name (taking container names into consideration) to prevent duplicate ID’s. This will break your old id based javascript. I wrote the following functions to find the original control by passing in its origininal id or name:

function getElementByPartialName(strPartialName)
{
if (strPartialName.length == 0)
{
return false;
}
var iForms = document.forms.length;
var iFrm;
var iElements;
var iElm;
var iPartialNameLength = strPartialName.length;
var iElementNameLength;
var iPartNamePosition;
for (iFrm = 0; iFrm < iForms; iFrm++)
{
iElements = document.forms[iFrm].elements.length;
for (iElm = 0; iElm < iElements; iElm++){
iPartialNamePosition = document.forms[iFrm].elements[iElm].name.indexOf(strPartialName);
if (iPartialNamePosition > -1){
iElementNameLength = document.forms[iFrm].elements[iElm].name.length;
if (iElementNameLength – (iPartialNamePosition + iPartialNameLength) == 0)
{
return document.forms[iFrm].elements[iElm]; //found, return element object
}
}
}
}
return false; //element not found. comment this line if
//return of false will cause an error (most cases)

}

function getElementByPartialId(strPartialId)
{
if (strPartialId.length == 0)
{
return false;
}
var iForms = document.forms.length;
var iFrm;
var iElements;
var iElm;
var iPartialIdLength = strPartialId.length;
var iElementIdLength;
var iPartIdPosition;
for (iFrm = 0; iFrm < iForms; iFrm++)
{
iElements = document.forms[iFrm].elements.length;
for (iElm = 0; iElm < iElements; iElm++){
iPartialIdPosition = document.forms[iFrm].elements[iElm].id.indexOf(strPartialId);
if (iPartialIdPosition > -1){
iElementIdLength = document.forms[iFrm].elements[iElm].id.length;
if (iElementIdLength – (iPartialIdPosition + iPartialIdLength) == 0)
{
return document.forms[iFrm].elements[iElm]; //found, return element object
}
}
}
}
return false; //element not found. comment this line if
//return of false will cause an error (most cases)
}

So, when you need to call an element by its original id or name, you can use getElementByPartialId(originalID) or getElementByPartialName(originalName) instead. It’s not pretty, but it works.

Example:

<body onload=”javascript:someJavaScript(getElementByPartialId(‘originalID’));”>…</body>

*Note: As coded here, the function will only return an element if the Id or Name appears at the end of the new ID or name, ie: item getElementByPartialId(‘testid’) will return the proper object if the new id is “xx_xx_xx_testid” but not if the new id is “xx_xx_xx_testidx” This is for 2 reasons: 1 – as far as my experience with Master pages goes, the original name is always the last part (could be wrong, my experience with MP was brief and limited) and 2 – if you were to getElementByPartialId() of any 1 letter or number, you may return multiple elements, which this is not designed to handle.