This is a demonstration of how to over-ride the default window.alert
method of a browser.
This was born from the design requirements of a recent project to have non-standard alerts to notify the user of a problem with data they had entered. The trick here was that all products use the same validation scripts, and not all of them fell under this requirement.
To modify the validation scripts to expect another argument that would have told it to use a DIV overlay or a standard alert would have proven difficult to implement and maintain. A co-worker (Dean) wondered out loud if it was possible to overload the alert method, and turns out - you can.
You can test the alert functionality with the following button. You can also type javascript:alert("Hello World");
from your browsers URL bar to see it work.
The markup for the above button is:
<input type="button" value = "Test the alert" onclick="alert('This is a custom alert dialog that was created by over-riding the window.alert method.');" />
Psuedo-modality is achieved by using a 100% wide and 100% tall absolutely positioned DIV element that acts as the parent element of the custom alert. This DIV overlays everything on the page and prevents user interaction with elements other than the custom alert. Note that a 1x1 transparent png image is set as the background-image -- this prevents MSIE from allowing the parent DIV to be "hollow", which would defeat its purpose.
Only one alert can exist at a time -- the function will return if it detects the existence of a previous instance of the "modalContainer" parent element. Hitting the "Ok" button will remove the "modalContainer" element from the DOM along with its child elements and hand control of the page back to the user.
In browsers that support position:fixed
, meaning all of them except MSIE6 and lower, the alert will stay with the user as they scroll. Thanks to Kevin for the education on that property value.
This has been tested and verified to work in MSIE6, Firefox 1.0, Safari and Opera 7.1+.
Note: This is a demonstration only. I am not saying that this is a production worthy alternative to the default behavior of the window.alert method as it does not allow for true modality. I am only showing what is possible - implement at your own risk. Feel free to contact me with any suggestions.
// constants to define the title of the alert and button text.
var ALERT_TITLE = "Oops!";
var ALERT_BUTTON_TEXT = "Ok";
// over-ride the alert method only if this a newer browser.
// Older browser will see standard alerts
if(document.getElementById) {
window.alert = function(txt) {
createCustomAlert(txt);
}
}
function createCustomAlert(txt) {
// shortcut reference to the document object
d = document;
// if the modalContainer object already exists in the DOM, bail out.
if(d.getElementById("modalContainer")) return;
// create the modalContainer div as a child of the BODY element
mObj = d.getElementsByTagName("body")[0].appendChild(d.createElement("div"));
mObj.id = "modalContainer";
// make sure its as tall as it needs to be to overlay all the content on the page
mObj.style.height = document.documentElement.scrollHeight + "px";
// create the DIV that will be the alert
alertObj = mObj.appendChild(d.createElement("div"));
alertObj.id = "alertBox";
// MSIE doesnt treat position:fixed correctly, so this compensates for positioning the alert
if(d.all && !window.opera) alertObj.style.top = document.documentElement.scrollTop + "px";
// center the alert box
alertObj.style.left = (d.documentElement.scrollWidth - alertObj.offsetWidth)/2 + "px";
// create an H1 element as the title bar
h1 = alertObj.appendChild(d.createElement("h1"));
h1.appendChild(d.createTextNode(ALERT_TITLE));
// create a paragraph element to contain the txt argument
msg = alertObj.appendChild(d.createElement("p"));
msg.innerHTML = txt;
// create an anchor element to use as the confirmation button.
btn = alertObj.appendChild(d.createElement("a"));
btn.id = "closeBtn";
btn.appendChild(d.createTextNode(ALERT_BUTTON_TEXT));
btn.href = "#";
// set up the onclick event to remove the alert when the anchor is clicked
btn.onclick = function() { removeCustomAlert();return false; }
}
// removes the custom alert from the DOM
function removeCustomAlert() {
document.getElementsByTagName("body")[0].removeChild(document.getElementById("modalContainer"));
}