Categories
Looking glass
Navigate/Search

Archive for the 'Javascript' Category

Master Page Name Mangling

Friday, April 11th, 2008

I just read over some of my oldest posts, and found this gem. While I stand by it still, the code is unreadable, and using some class names that will not be relevant to your project. Mayhaps a better approach would be to create a class to implement in pages where needed.

Again, this is really only needed when time is at a premium and you have legacy javascript that accesses page elements by ID that will be mangled by master pages.

Obviously, the best course of action is always to use the coding tools you have and not hack around them. Sometimes, that is not an option. That was the situation I was in when I wrote those posts. Shakespeare’s gotta get paid, son.

Enable Right Click

Wednesday, June 6th, 2007

UPDATE: Do not keep this script enabled, only use it as needed. It could cause some issues while browsing, as it loops through every HTML element on the page.

Greasemonkey script to reenable right clicking on sites that disable it for “security” purposes:

EnableRightClick.user.js

Code:
// ==UserScript==
// @name           enable right click
// @namespace      http://forrestledbetter.com
// @description    enable right click
// ==/UserScript==

if (document.all)
{
	iElements = document.all.length;

	for (i = 0;i < iElements;i++)
	{
		document.all[i].setAttribute("oncontextmenu", "return true;");
	}
}
else
{
	iElements = document.getElementsByTagName('*').length;
	aElements = document.getElementsByTagName('*');
	for (i = 0;i < iElements;i++)
	{
		aElements[i].setAttribute("oncontextmenu", "return true;");
	}

}

Functional Javascript

Thursday, April 19th, 2007

I found this blog on del.icio.us I think. This is by far the best explanation of the various ways to use functions in javascript. Don’t stop with this one, look at all the other posts. There is some pretty advanced stuff here, and javascript isn’t going anywhere any time soon.

Mono Project

Friday, February 23rd, 2007

Mono Project

Now you can write AND run .net code on pretty much anything, for free. With Mono’s newest release, you can use Visual Basic. I’m not sure why you would want to, but you can if you feel the urge.

Javascript libraries roundup

Thursday, January 11th, 2007

Here is a great post containing a list of several javascript libraries. These are great for speeding up web development. Form field validation, ajax, visual effects… each implemented with usually one line of code.

Pixel2life Free Tutorial Search Engine

Thursday, January 11th, 2007

Pixel2life is an awesome source of tech tutorials including graphic design, coding, 3D animation, photoshop, and on and on. There are tons of things to learn there.

Modal Dialog Forms

Friday, October 6th, 2006

Personally, I don’t like using Modal Dialogs because they are IE only - BUT some times thats what the client wants, so thats what they get. One of the biggest annoyances when using Modal Dialogs is the little quirk of opening a new window when trying to submit a form located within the dialog. The solution is easy enough, it just took a while for me to find so I thought I would post it here:

Code:
<head>
  <base target="_self" />
</head>

Thats it. I don’t recall where I found this exactly, but it was on some message board after scouring Google search results for quite some time.

So, how do you tell whether to use modals or pops? Thats a pretty easy one too, but its a pain because of all the extra coding required:

Code:
var oInput = new Object();
var oReturn = new Object();
if(!window.showModalDialog)
{
  //code for browsers not supporting modal dialogs goes here
  //
  window.open("testpop.htm","testpop","height:570px;width:700px;help:no;scroll:yes;"")
}
else
{
  //code for browsers supporting modals goes here
  oReturn = showModalDialog("testpop.htm", oInput, "dialogHeight:570px;dialogWidth:700px;center:yes;help:no;scroll:yes;");
  tstFormElement.value = oReturn.value;
}

This is more robust than checking whether the incoming browser is IE or not, because who knows when or if the other browsers will integrate modal dialogs? Of course, this just handles opening the window. If you want to manipulate any data on the page opening the dialog/pop, you have to place a similar block in the opened page because the opener is referenced differently. Wait…what?

Code:
if(!window.showModalDialog)
{
  //code for browsers not supporting modal dialogs goes here
  opener.document.getElementById('elementID').value = "test value";
}
else
{
  //code for browsers supporting modals goes here
  var oReturn = new Object();
  oReturn.value = "test value"
  //place code to change values when this object is returned
}

So the last (?) hurdle here, is making your faux modal window act like a modal dialog, which is to say, it retains focus and does not allow the user to return to the calling window. I wrote a basic script - placed in the opening window - checking whether the opened window was still open or not. If it was still open, the opener returned focus to the dialog. This worked nicely at first, but when I started hammering away at it I could get it to fail. If anyone has a better suggestion, please let me know - just don’t bring up Mozilla’s modal=true bs, because its crap and it doesn’t work - at least not for me. And even if it does, its only for Mozilla.

There are probably other techniques for this, but these work adequately for me when I am forced to take this route.

Modal Dialogs are bad. If you feel you have no other choice, take a step back and find another way. It will save you blood, sweat, and tears.

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.