
From a usability perspective, the advantage of using an internal DHTML dialog (rather than launching a new window or going to a new page - Internet Explorer's showModalDialog() would be a nice solution but it is not cross-browser) is that the interaction with the dialog remains contextually associated with the disabled page. This means for instance, that when your user wants to provide feedback or add detail to a page on your site, this implementation will visually indicate that the dialog element they are interacting with is inherently associated with the disabled page in the background.
From a code-maintainability perspective, this may introduce a code overhead that doesn't justify the usability benefit depending on your web applications implementation framework. It seems rather well suited to an 'AJAX'(y) style application.
This Tip shows how to create, handle & Display an Image or Photo Upload form in Ruby on Rails
DHTML Example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>DHTML Non-clickable protection DIV and in-screen modal dialog style display area using JavaScript DOM using CSS Opaque/Opacity filter</title>
<style type="text/css">
/* http://www.mandarindesign.com/opacity.html */
#internal_dialog { display:none; position:absolute; top:35px; left:150px; z-index:3; background-color:#6495ED; filter:alpha(opacity=100); -moz-opacity:1.00; opacity:1.00; border:3px solid white; margin:auto; color:white; padding:15px; }
.content_faded {filter:alpha(opacity=50); -moz-opacity:.50; opacity:.50; background-color: #000; z-index:2; position:absolute; left:0px; top:0px; width: 100%; height:100%;}
body, label {font-size:100%; font-family:verdana;}
h1, h2 {margin-bottom:0px; }
p {margin-top:0px;}
</style>
<script language="JavaScript">
var content_shield = null;
var modal_dialog = null;
function getPageSize(){
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) {
xScroll = document.body.scrollWidth;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
var windowWidth, windowHeight;
if (self.innerHeight) { // all except Explorer
windowWidth = self.innerWidth;
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = windowWidth;
} else {
pageWidth = xScroll;
}
arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
return arrayPageSize;
}
function launch_file_upload_internal_dialog() {
//In this example, just display some form elements. This could easily be replaced with a call to an iframe
var dialog_html = "<label for='file_input'>Specify a file to upload:</label><input type='file' id='file_input'/><input type='button' value='submit' onclick='hide_modal_dialog()'/>";
dialog_html += "<input type='button' value='close' onclick='hide_modal_dialog()' style='margin-left:30px;'/>";
show_modal_dialog(dialog_html);
}
function body_onscroll() {
window.status = getScrollXY();
}
function show_modal_dialog(dialog_html) {
if (content_shield == null) {
content_shield = document.createElement("div");
content_shield.style.height = getPageSize()[1];
document.body.appendChild(content_shield);
content_shield.className = "content_faded";
window.status="disabled";
//Because the div is only ever going to be the height of the displayable area of the browser (100%),
//it needs to move with the scrollbars (width will always be 100%). We could instead explicitly set
//div height to the complete height of the page including non-visible scrollable areas, but then
//we would need to handle window resize events as well.
//eg. addEvent(document.body, "onscroll", body_onscroll);
}
modal_dialog = document.getElementById("internal_dialog");
modal_dialog.innerHTML = dialog_html;
modal_dialog.style.display = "block";
}
function hide_modal_dialog() {
modal_dialog.style.display = "none";
if (content_shield != null) {
document.body.removeChild(content_shield);
content_shield = null;
}
}
function addEvent(obj, evType, fn, useCapture){
//From http://www.scottandrew.com/weblog/articles/cbs-events
if (obj.addEventListener){
obj.addEventListener(evType, fn, useCapture);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be attached");
}
}
function getScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return [ scrOfX, scrOfY ];
}
</script>
</head>
<body>
<div id="internal_dialog"></div>
<input type="button" value="Launch Internal Dialog" onclick="launch_file_upload_internal_dialog()"/>
</body>
</html>