Categories
Looking glass
Navigate/Search

Archive for September 18th, 2006

Notepad++

Monday, September 18th, 2006

Notepad++ is an awesome text editor. Its a great replacement for classic notepad. My two favorite features are visible line numbers and tab visualization. If you do any kind of coding and need a quick, lightweight text editor for those tasks too small to bring into a full service IDE, this is perfect.

Name Mangling, Solution 3

Monday, September 18th, 2006

UPDATE:
Master pages are quite useful. Use them when applicable, but pay careful attention when you have thousands of lines of legacy javascript. I will leave the original post as is…this is a learning experience for me as well. Note my frustration below:
/UPDATE
UPDATE 2:
Paragraph 2 doesn’t make any sense to people that were not working on that project. I should have made this much more generic
/UPDATE 2

My suggestion: don’t use Master Pages. That is, until MS releases a tool to retrofit your existing javascripts or prevent master pages from name mangling. From what I hear, it is hell on CSS as well, but I haven’t run into that yet.

Instead, I just created 2 user controls, one containing the head of my layout, and one containing the footer. Simple enough for me, and I don’t have to waste time figuring out why my scripts don’t work. If that’s not good enough for you, you’ll need to make use of the .clientID property in your code behind pages - it just was not a viable option in my particular case.

Name Mangling, Solution 2

Monday, September 18th, 2006

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

Monday, September 18th, 2006

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.