Skip to content

Instantly share code, notes, and snippets.

@wizard04wsu
Last active July 1, 2020 17:53
Show Gist options
  • Save wizard04wsu/11452844 to your computer and use it in GitHub Desktop.
Save wizard04wsu/11452844 to your computer and use it in GitHub Desktop.
This script (and CSS stylesheet) allows you to create a custom modal dialog box that will not allow the user to interact with the rest of the page.
.modalMask {
display:none;
}
.modalMask.active {
display:block;
position:fixed;
top:0;
left:0;
bottom:0;
right:0;
z-index:1000;
overflow:auto;
}
.modalFocusButton, .modalBlurButton, #modalBodyBlurButton {
display:block;
position:absolute;
width:1px; /*for Safari*/
height:1px; /*for Safari*/
overflow:hidden;
padding:0; border:0; outline:0; margin:-1px;
background:transparent; color:transparent;
}
.modalMaskOverlay {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
background-color:gray;
opacity:0.5;
filter: alpha(opacity=50); /*for IE 8*/
}
.modalTable, .modalTableIE {
position:relative;
display:table;
height:100%;
margin:0 auto;
}
.modalCell, .modalCellIE {
display:table-cell;
vertical-align:middle;
}
.modalContent {
margin:auto;
padding:11px;
overflow:auto;
background-color:#FFF;
border:5px solid #888;
-moz-border-radius:16px;
-webkit-border-radius:16px;
-khtml-border-radius:16px;
border-radius:16px;
-moz-box-shadow:0 0 80px 0 #000;
-webkit-box-shadow:0 0 80px #000;
box-shadow:0 0 80px #000;
/*dialog box width (minus padding & border)*/
min-width:368px; /*400px*/
max-width:668px; /*700px*/
/*dialog box height (minus padding & border)*/
min-height:168px; /*200px*/
max-height:668px; /*700px*/
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Modal Dialog Box</title>
<style type="text/css" media="all">
.modalContent {
font-family:Arial, Helvetica, sans-serif;
font-size:0.9em;
}
body {
padding:8px;
}
#filler {
display:none;
color:#666;
}
</style>
<link rel="stylesheet" type="text/css" media="all" href="modalDialog4.css">
<script type="text/javascript" src="modalDialog4.js"></script>
<script type="text/javascript">
function toggleFiller(btn){
if(btn.innerHTML == "Show More Content"){
document.getElementById("filler").style.display = "block";
btn.innerHTML = "Show Less Content";
}
else{
document.getElementById("filler").style.display = "none";
btn.innerHTML = "Show More Content";
}
}
</script>
</head>
<body>
<script type="text/javascript">
var dialog1 = createModalDialog();
dialog1.dialog.innerHTML = "<p style=\"margin-top:0;\">" +
"When this dialog box is displayed, you cannot interact with the rest of the document." +
"</p>" +
"<ul>" +
" <li><b>Text cannot be directly selected</b>. However, <em>all</em> browsers let you select-all " +
" (<kbd>Ctrl+A</kbd>).</li>" +
" <li>Clicks and other <b>common events do not fire</b>. (There's no practical way to block <em>all</em> events.)</li>" +
" <li><b>Nothing can be scrolled</b> using the mouse or keyboard.</li>" +
" <li><b>Elements cannot be focused</b> (using the tab key, for example). This includes form elements, links, " +
" etc. Pressing <kbd>Shift+Tab</kbd> will still get you to the browser chrome (except in Opera).</li>" +
"</ul>" +
"<p>" +
"When the dialog is dismissed, focus is restored to the element that had it before the dialog was displayed." +
"</p>" +
"<p>" +
"If the dialog box is larger than the viewport, scrollbars should appear." +
"</p>" +
"<button onclick=\"dialog1.close()\">Close</button>";
dialog1.setOverlay("red", "0.1");
var dialog2 = createModalDialog(true);
dialog2.dialog.innerHTML = "<p style=\"margin-top:0;\">You can click outside of this dialog box to close it.</p><button onclick=\"dialog2.close()\">Close</button>";
dialog2.setOverlay("#000", 0.75);
</script>
<h1>Modal Dialog Box</h1>
<p>
<button onclick="dialog1.open()">Show Modal #1</button><br>
<button onclick="dialog2.open()">Show Modal #2</button>
</p>
<p>
<button onclick="toggleFiller(this)">Show More Content</button>
<div id="filler">
<p>
<select><option>Option</option></select>
<input type="button" value="Button Input">
<button>Button</button>
<textarea>Textarea</textarea>
</p>
<p style="white-space:nowrap;">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Sed sed enim. Suspendisse eleifend tellus vitae tortor. Aliquam at nisl non velit malesuada facilisis. Nunc adipiscing lacinia nibh. Sed tincidunt tellus in lectus. Nunc mattis aliquam odio. Quisque scelerisque felis at purus. Phasellus vel nunc a eros tristique faucibus. In luctus eros vulputate sapien. Praesent auctor. Aliquam scelerisque erat in metus rutrum euismod. Nulla ut enim. Curabitur sit amet metus non eros molestie vulputate. Morbi dui velit, tempor et, rutrum sed, elementum quis, purus. Quisque a pede ac erat hendrerit venenatis. Nulla nibh urna, consectetuer eget, luctus non, accumsan eget, orci. In quis pede.
</p>
<p>
Ut tincidunt, risus non adipiscing venenatis, libero massa mattis velit, a mattis justo velit mollis felis. Nulla neque. Suspendisse ut magna. Nam felis nibh, consectetuer in, aliquet ac, venenatis quis, justo. Duis in nulla ac ante imperdiet feugiat. Nullam pede. Curabitur commodo leo ut lectus. Duis nonummy, risus quis vehicula convallis, ipsum lorem ultrices orci, a imperdiet nisi justo eget magna. Etiam tristique ultricies purus. Etiam non mauris. Sed sodales. In hac habitasse platea dictumst. Duis in nisl. Vestibulum at lectus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas lacinia.
</p>
<p>
Cras condimentum, turpis at pulvinar mollis, velit turpis vestibulum purus, vel aliquet mi lorem non mauris. Vivamus rhoncus facilisis diam. Vestibulum condimentum nulla ut orci. Vivamus ultricies, nibh ut faucibus pulvinar, urna lorem hendrerit nulla, ac vehicula pede ante eget magna. Suspendisse gravida commodo tortor. Donec justo. Donec at lacus non odio volutpat porttitor. In hac habitasse platea dictumst. Phasellus pretium nulla. Suspendisse ut diam. Integer convallis, quam at vulputate pellentesque, diam dolor cursus leo, non tristique tellus massa at sapien. Nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce suscipit leo a nulla. Maecenas pellentesque sapien eget arcu. Donec mattis, nisl vestibulum condimentum sodales, quam urna venenatis nibh, a venenatis dolor orci eget enim. Donec condimentum, nulla eu consectetuer rhoncus, nisi purus dictum eros, eget tincidunt orci metus et purus. Proin venenatis ante et nibh. Vivamus fermentum.
</p>
<p>
Nulla facilisi. Maecenas vitae lorem eget nisi blandit consequat. Nam ac nisi. Pellentesque rutrum lorem at ipsum feugiat tincidunt. Ut quis erat. Nam augue. Donec interdum orci nec quam. Pellentesque tortor urna, consequat elementum, consequat fringilla, rhoncus quis, eros. Aliquam quam. Sed vel ligula. Proin consectetuer facilisis justo. Vivamus vel lorem a ipsum venenatis ullamcorper. In magna diam, egestas ac, scelerisque ut, convallis eget, mauris.
</p>
<p>
Praesent sapien eros, congue in, euismod et, pellentesque at, sem. Nullam semper eleifend ligula. Morbi ligula. Nam sit amet velit. Sed eget dui. Maecenas et felis. Sed augue ipsum, tincidunt viverra, semper vel, dapibus non, est. Morbi in augue sed turpis vehicula pretium. Nulla vitae lorem. Donec sit amet sapien sed risus dictum mollis. Duis vel enim ut ligula laoreet semper. Aenean tempor velit at felis. Integer eu nisl a ligula tempor aliquet.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Sed sed enim. Suspendisse eleifend tellus vitae tortor. Aliquam at nisl non velit malesuada facilisis. Nunc adipiscing lacinia nibh. Sed tincidunt tellus in lectus. Nunc mattis aliquam odio. Quisque scelerisque felis at purus. Phasellus vel nunc a eros tristique faucibus. In luctus eros vulputate sapien. Praesent auctor. Aliquam scelerisque erat in metus rutrum euismod. Nulla ut enim. Curabitur sit amet metus non eros molestie vulputate. Morbi dui velit, tempor et, rutrum sed, elementum quis, purus. Quisque a pede ac erat hendrerit venenatis. Nulla nibh urna, consectetuer eget, luctus non, accumsan eget, orci. In quis pede.
</p>
<p>
Ut tincidunt, risus non adipiscing venenatis, libero massa mattis velit, a mattis justo velit mollis felis. Nulla neque. Suspendisse ut magna. Nam felis nibh, consectetuer in, aliquet ac, venenatis quis, justo. Duis in nulla ac ante imperdiet feugiat. Nullam pede. Curabitur commodo leo ut lectus. Duis nonummy, risus quis vehicula convallis, ipsum lorem ultrices orci, a imperdiet nisi justo eget magna. Etiam tristique ultricies purus. Etiam non mauris. Sed sodales. In hac habitasse platea dictumst. Duis in nisl. Vestibulum at lectus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas lacinia.
</p>
<p>
Cras condimentum, turpis at pulvinar mollis, velit turpis vestibulum purus, vel aliquet mi lorem non mauris. Vivamus rhoncus facilisis diam. Vestibulum condimentum nulla ut orci. Vivamus ultricies, nibh ut faucibus pulvinar, urna lorem hendrerit nulla, ac vehicula pede ante eget magna. Suspendisse gravida commodo tortor. Donec justo. Donec at lacus non odio volutpat porttitor. In hac habitasse platea dictumst. Phasellus pretium nulla. Suspendisse ut diam. Integer convallis, quam at vulputate pellentesque, diam dolor cursus leo, non tristique tellus massa at sapien. Nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce suscipit leo a nulla. Maecenas pellentesque sapien eget arcu. Donec mattis, nisl vestibulum condimentum sodales, quam urna venenatis nibh, a venenatis dolor orci eget enim. Donec condimentum, nulla eu consectetuer rhoncus, nisi purus dictum eros, eget tincidunt orci metus et purus. Proin venenatis ante et nibh. Vivamus fermentum.
</p>
<p>
Nulla facilisi. Maecenas vitae lorem eget nisi blandit consequat. Nam ac nisi. Pellentesque rutrum lorem at ipsum feugiat tincidunt. Ut quis erat. Nam augue. Donec interdum orci nec quam. Pellentesque tortor urna, consequat elementum, consequat fringilla, rhoncus quis, eros. Aliquam quam. Sed vel ligula. Proin consectetuer facilisis justo. Vivamus vel lorem a ipsum venenatis ullamcorper. In magna diam, egestas ac, scelerisque ut, convallis eget, mauris.
</p>
<p>
Praesent sapien eros, congue in, euismod et, pellentesque at, sem. Nullam semper eleifend ligula. Morbi ligula. Nam sit amet velit. Sed eget dui. Maecenas et felis. Sed augue ipsum, tincidunt viverra, semper vel, dapibus non, est. Morbi in augue sed turpis vehicula pretium. Nulla vitae lorem. Donec sit amet sapien sed risus dictum mollis. Duis vel enim ut ligula laoreet semper. Aenean tempor velit at felis. Integer eu nisl a ligula tempor aliquet.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Sed sed enim. Suspendisse eleifend tellus vitae tortor. Aliquam at nisl non velit malesuada facilisis. Nunc adipiscing lacinia nibh. Sed tincidunt tellus in lectus. Nunc mattis aliquam odio. Quisque scelerisque felis at purus. Phasellus vel nunc a eros tristique faucibus. In luctus eros vulputate sapien. Praesent auctor. Aliquam scelerisque erat in metus rutrum euismod. Nulla ut enim. Curabitur sit amet metus non eros molestie vulputate. Morbi dui velit, tempor et, rutrum sed, elementum quis, purus. Quisque a pede ac erat hendrerit venenatis. Nulla nibh urna, consectetuer eget, luctus non, accumsan eget, orci. In quis pede.
</p>
<p>
Ut tincidunt, risus non adipiscing venenatis, libero massa mattis velit, a mattis justo velit mollis felis. Nulla neque. Suspendisse ut magna. Nam felis nibh, consectetuer in, aliquet ac, venenatis quis, justo. Duis in nulla ac ante imperdiet feugiat. Nullam pede. Curabitur commodo leo ut lectus. Duis nonummy, risus quis vehicula convallis, ipsum lorem ultrices orci, a imperdiet nisi justo eget magna. Etiam tristique ultricies purus. Etiam non mauris. Sed sodales. In hac habitasse platea dictumst. Duis in nisl. Vestibulum at lectus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas lacinia.
</p>
<p>
Cras condimentum, turpis at pulvinar mollis, velit turpis vestibulum purus, vel aliquet mi lorem non mauris. Vivamus rhoncus facilisis diam. Vestibulum condimentum nulla ut orci. Vivamus ultricies, nibh ut faucibus pulvinar, urna lorem hendrerit nulla, ac vehicula pede ante eget magna. Suspendisse gravida commodo tortor. Donec justo. Donec at lacus non odio volutpat porttitor. In hac habitasse platea dictumst. Phasellus pretium nulla. Suspendisse ut diam. Integer convallis, quam at vulputate pellentesque, diam dolor cursus leo, non tristique tellus massa at sapien. Nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce suscipit leo a nulla. Maecenas pellentesque sapien eget arcu. Donec mattis, nisl vestibulum condimentum sodales, quam urna venenatis nibh, a venenatis dolor orci eget enim. Donec condimentum, nulla eu consectetuer rhoncus, nisi purus dictum eros, eget tincidunt orci metus et purus. Proin venenatis ante et nibh. Vivamus fermentum.
</p>
</div>
</body>
</html>
//This script (and CSS stylesheet) allows you to create a custom modal dialog box that will not allow
// the user to interact with the rest of the page.
//
// - Text cannot be directly selected. However, all browsers let you select-all (Ctrl+A).
// - Clicks and other common events do not fire. (There's no practical way to block *all* events.)
// - Nothing can be scrolled using the mouse or keyboard.
// - Elements cannot be focused (using the tab key, for example). This includes form elements, links, etc.
// Pressing Shift+Tab will still get you to the browser chrome (except in Opera).
//
//When the dialog is dismissed, focus is restored to the element that had it before the dialog was displayed.
//
//If the dialog box is larger than the viewport, scrollbars should appear.
//createModalDialog([closeOnOverlayClick]) //creates a blank dialog box and inserts it at the beginning of <body>
// closeOnOverlayClick //(optional) if true, clicking outside of the dialog box will close it
//it returns an object with these attributes:
// dialog //the div element containing the content of the dialog box; put the content in this element
// setOverlay(color, opacity) //set the CSS background color and/or opacity of the overlay behind the dialog box
// open() //open the dialog
// close() //close the dialog
// remove() //delete the dialog
var createModalDialog = (function (){
"use strict";
var modalIsDisplayed, scrollPosition = {}, focusedElement = null;
function saveScrollPosition(){
var top, left;
if(!isNaN(window.pageYOffset)){ //all except IE
top = window.pageYOffset;
left = window.pageXOffset;
}
else{
//IE quirks mode
top = document.body.scrollTop;
left = document.body.scrollLeft;
//IE standards compliance mode
if(document.documentElement && document.documentElement.scrollTop){
top = document.documentElement.scrollTop;
left = document.documentElement.scrollLeft;
}
}
scrollPosition.top = top || 0;
scrollPosition.left = left || 0;
}
function restoreScrollPosition(){
//which of these to use seems to depend on whether the browser is in quirks mode or not
try{ document.body.scrollTop = scrollPosition.top; }catch(e){}
try{ document.documentElement.scrollTop = scrollPosition.top; }catch(e){}
try{ document.body.scrollLeft = scrollPosition.left; }catch(e){}
try{ document.documentElement.scrollLeft = scrollPosition.left; }catch(e){}
}
function show(mask){
var blurButton;
if(modalIsDisplayed) return; //a dialog is already being displayed
//save the focus
focusedElement = document.activeElement || focusedElement;
//disable scrolling
saveScrollPosition();
document.documentElement.style.width = document.documentElement.clientWidth+"px";
document.documentElement.style.height = document.documentElement.clientHeight+"px";
document.documentElement.style.top = (-scrollPosition.top)+"px";
document.documentElement.style.left = (-scrollPosition.left)+"px";
document.documentElement.style.position = "fixed";
//make sure this mask is the first element in the body
document.body.insertBefore(mask, document.body.firstChild);
//show the dialog box
mask.className += " active";
//add button to the end of <body> to redirect focus from the browser chrome via shift+tab
blurButton = document.createElement("button");
blurButton.id = "modalBodyBlurButton";
blurButton.innerHTML = " ";
blurButton.onfocus = function (){ getByClassName(mask, "modalBlurButton")[0].focus(); };
document.body.appendChild(blurButton);
//put focus in the dialog box
getByClassName(mask, "modalFocusButton")[0].focus();
modalIsDisplayed = true;
}
function hide(mask){
if(!(/(^|\s+)active(\s+|$)/).test(mask.className)) return; //this dialog is not visible
//hide the dialog box
mask.className = mask.className.replace(/(^|\s+)active(\s+|$)/g, " ");
//remove the redirect focus button from <body>
document.body.removeChild(document.getElementById("modalBodyBlurButton"));
//restore the focus
if(focusedElement) focusedElement.focus();
//enable scrolling
document.documentElement.style.position = "";
document.documentElement.style.top = "";
document.documentElement.style.left = "";
document.documentElement.style.width = "";
document.documentElement.style.height = "";
restoreScrollPosition();
modalIsDisplayed = false;
}
function confineEvent(evt){
evt = evt || event;
if(evt.stopPropagation) evt.stopPropagation();
else evt.cancelBubble = true;
}
function addHandler(obj, type, handler){
if(window.addEventListener) obj.addEventListener(type, handler, false);
else obj.attachEvent("on"+type, handler);
}
function getByClassName(elem, classname){
var descendants, i, rxp, withClass = [];
if(elem.getElementsByClassName){
return elem.getElementsByClassName(classname);
}
else{
descendants = elem.getElementsByTagName("*");
rxp = new RegExp("(^|\s)"+classname+"(\s|$)");
for(i=0; i<descendants.length; i++){
if(rxp.test(descendants[i].className)){
withClass.push(descendants[i]);
}
}
return withClass;
}
}
function createModalDialog(closeOnOverlayClick){
var mask, focus, overlay, content_table, content_cell,
content_IE_table, content_IE_tbody, content_IE_tr, content_IE_td,
blur, obj = {};
//mask
mask = document.createElement("div");
mask.className = "modalMask";
obj.open = function (){ show(mask); };
obj.close = function (){ hide(mask); };
obj.remove = function (){
if(/(^|\s+)active(\s+|$)/.test(mask.className)) obj.close();
try{ document.body.removeChild(mask); }catch(e){}
mask = null;
delete obj.open;
delete obj.close;
delete obj.remove;
delete obj.setOverlay;
delete obj.dialog;
};
//focus button
focus = document.createElement("button");
focus.className = "modalFocusButton";
focus.innerHTML = " ";
mask.appendChild(focus);
//overlay
overlay = document.createElement("div");
overlay.className = "modalMaskOverlay";
mask.appendChild(overlay);
obj.setOverlay = function (color, opacity){
if(color !== "transparent" || document.addEventListener){
if(color){
overlay.style.backgroundColor = color;
}
if(opacity || opacity===0){
overlay.style.opacity = opacity;
overlay.style.filter = "alpha(opacity="+(100*opacity)+")"; //for IE8
}
}
else{ //transparent background color messes things up in IE8
overlay.style.backgroundColor = "#FFF";
overlay.style.filter = "alpha(opacity=0)";
}
};
//content
content_table = document.createElement("div");
content_table.className = "modalTable";
mask.appendChild(content_table);
content_cell = document.createElement("div");
content_cell.className = "modalCell";
content_table.appendChild(content_cell);
//dialog box
obj.dialog = document.createElement("div");
obj.dialog.className = "modalContent";
content_cell.appendChild(obj.dialog);
//blur button
blur = document.createElement("button");
blur.className = "modalBlurButton";
blur.innerHTML = " ";
blur.onfocus = function (){ getByClassName(mask, "modalFocusButton")[0].focus(); };
mask.appendChild(blur);
//only the most common events will be blocked by the mask
addHandler(mask, "click", confineEvent);
addHandler(mask, "dblclick", confineEvent);
addHandler(mask, "keydown", confineEvent);
addHandler(mask, "keypress", confineEvent);
addHandler(mask, "keyup", confineEvent);
addHandler(mask, "mousedown", confineEvent);
addHandler(mask, "mouseup", confineEvent);
addHandler(mask, "contextmenu", confineEvent);
addHandler(mask, "mousemove", confineEvent);
addHandler(mask, "mouseover", confineEvent);
addHandler(mask, "mouseenter", confineEvent);
addHandler(mask, "mouseleave", confineEvent);
addHandler(mask, "mouseout", confineEvent);
addHandler(mask, "mousewheel", confineEvent);
addHandler(mask, "scroll", confineEvent);
addHandler(mask, "reset", confineEvent);
addHandler(mask, "submit", confineEvent);
if(closeOnOverlayClick){
//close the modal when you click outside of the dialog box
addHandler(getByClassName(mask, "modalContent")[0], "click", confineEvent);
addHandler(getByClassName(mask, "modalCell")[0], "click", obj.close);
addHandler(getByClassName(mask, "modalMaskOverlay")[0], "click", obj.close);
}
return obj;
};
//for Safari, since document.activeElement isn't supported
if(document.addEventListener){
document.addEventListener("focus", function (evt){ if(!modalIsDisplayed) focusedElement = evt.target; }, true);
}
return createModalDialog;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment