Here's a little nugget from Perk's bag of tricks.
Personally, I like to see my web pages mimic normal applications as much as possible. I think that Windows, Apple, Gnome, KDE etc etc have done a fine job of training people, so why reinvent the wheel? To this end, it's always bugged me that you can't myObj.disable() or disable(anObj) from HTML. Here is a way to emulate that behavior.
The trick relies on a couple important features of Javascript and CSS:
- The ability to create a new DIV on the fly
- The ability to find a target object's top/left/height/width coordinates
- The ability to use z-index to put a new div "in front" of an existing div
- When one div is on top of another, you can't click anything that's behind it
- The ability for a PNG(24) to do alpha blending as a background image.
Here is an example, from one of my retail sites, before the "Confirm and Purchase" button is pressed and after. Note the buttons (munged to protect the innocent):


As mentioned above, I have a simple little function that you pass an existing element on a webpage, and a mask graphic. (there's actually 2 mask graphics, but I'll cover that in a bit).
Here is the actual function (and two other little functions it requires):
function disable(targetID, maskURLNew, maskURLOld)
{
// If a string was passed as targetID, then find the node.
// If it's not a string, assume it is a passed node.
if (typeof(targetID) == 'string') var target = document.getElementById(targetID);
else var target = targetID;
// Get a handle to the main document body
var bodies = document.getElementsByTagName('BODY');
var base = bodies[0];
// Get the position and dimensions of the target element
var top = getElementTop(target);
var left = getElementLeft(target);
var height = target.offsetHeight;
var width = target.offsetWidth;
// Use maskURLOld if the browser is IE6 or less
var bImage = maskURLNew;
var bVer = navigator.appVersion;
ver = bVer.match(/MSIE ([0-9])/);
if (ver != null)
{
if (ver[1] != undefined)
{
vNum = (ver[1] - 0);
if (vNum <= 6) bImage = maskURLOld;
}
}
// Create the new div and attribute it accordingly
var newDiv = document.createElement('DIV');
newDiv.style.position = 'absolute';
newDiv.style.zIndex = '1000000';
newDiv.style.top = top + 'px';
newDiv.style.left = left + 'px';
newDiv.style.height = height + 'px';
newDiv.style.width = width + 'px';
newDiv.style.backgroundImage = 'url("' + bImage + '")';
newDiv.style.backgroundRepeat = 'repeat';
newDiv.innerHTML = ' ';
// Add the div to the main body and we're done
base.appendChild(newDiv);
}
function getElementLeft(obj)
{
var curleft = 0;
if(obj.offsetParent)
{
while(true)
{
curleft += obj.offsetLeft;
if(!obj.offsetParent) { break; }
obj = obj.offsetParent;
}
} else if(obj.x) { curleft += obj.x; }
return curleft;
}
function getElementTop(obj)
{
var curtop = 0;
if(obj.offsetParent)
{
while(true)
{
curtop += obj.offsetTop;
if(!obj.offsetParent) { break; }
obj = obj.offsetParent;
}
} else if(obj.y) { curtop += obj.y; }
return curtop;
}
Here is the actual code that makes the above two graphics happen (lightly munged, but not functionally)
function executeTransaction()
{
disable('buttonChangeBilling', '/graphics/whiteMask.png', '/graphics/whiteMask.gif');
disable('buttonChangeDelivery', '/graphics/whiteMask.png', '/graphics/whiteMask.gif');
disable('buttonChangeFOP', '/graphics/whiteMask.png', '/graphics/whiteMask.gif');
disable('cpirReceiptButtons', '/graphics/whiteMask.png', '/graphics/whiteMask.gif');
disable('cpirButtonLogout', '/graphics/whiteMask.png', '/graphics/whiteMask.gif');
disable('cartUpdateButton', '/graphics/blackMask.png', '/graphics/blackMask.gif');
...
}
Here are the links to each of the 4 graphics in this example:
whiteMask.png

whiteMask.gif

<-- it's really right there
blackMask.png

blackMask.gif

Reading the code should be relatively self explanatory. The trick does not work as nicely on IE6 or less, because it won't do an alpha blend. So the second graphic passed is a 2x2 GIF with 1 white dot and 3 transparent dots. So in IE6 it looks mottled, but is still clearly no longer available. Note also how I've supplied different masks for the cart portion - a black one - because the trick only works correctly if you mask with the same color as the background you're on top of.
The PNG graphics are simply a Photoshop graphic, all white/black/whatever with the opacity set to about 50% (to taste, of course). Then saved as a PNG(24) not a PNG(8 ). There is a *tiny* amount of overhead repeating the graphic all over your new DIV, so the bigger the background image the better. Since the GIF is barely used and I'm lazy, I just made it tiny. It people are still using IE6 then they can deal with a slightly slower effect LOL.
Here is an example of it in IE6 with a GIF style transparency:

Note also that in most cases, I selected the button to disable. But I am also able to disable divs the same way, like the div that contains my radio button divs, or the div at the top that has the caption and button to log out.
I am certain that this has problems somewhere as it has only been ground out with Safari, FF/Mac, IE7, IE6 and FF3 for Windows, but that's a reasonable enough starting place.
Enjoy!
/p