The goal of this example is to make all elements on and HTML form un-selectable while something like a Save/Load/long database lookup is happening. What we’ll do is superimpose a div over an HTML form, and have that div show opaque lines over the form as well as a clear area that says Loading or Saving.
We’ll make the page look like the image to the left, so that it is clear to the user that the form they were working on is temporarily disabled.
Setting things up:
As I mentioned at the start of this article, the goal is to disable an HTML form during a long-lasting process like a database lookup, or a load or a save event. Here we’ll be handling the visual representation of showing the form grayed along with a very obvious message showing what is happening and why the form has become non-editable. This is done using a div element that occupies the entire screen and is super-imposed over top of the HTML form fields. You may need to add extra code to disable the underlying form, but this example shows you how you can visually lock and unlock your HTML form.
Although this example uses pure HTML/JavaScript, I’ll also be importing Bootstrap for its UI formatting and Glyphicons, which are great for quickly sprucing up your HTML. If you want to use something else, you can simply remove the Bootstrap markup. This example is fully functional on its own in just HTML, CSS, and JavaScript.
Explaining the Example:
1) This example code simulates a longer save action using a JavaScript 5-second timeout using the setTimeOut command. Obviously, you’ll need to hook up your save/load/etc. behavior so the unload/re-enabling of your HTML form happens when it makes sense.
For example, if you were coding the Save message in a .NET WebForm, you’d want the page to disable itself while it is saving after the user clicks a ‘Save‘ button. In this case, you’d call the showLoadingDiv() function in the HTML form onSubmit event. Then after processing the code-behind and showing the locked screen, the page would naturally reload itself without the lock screen after the postback event had happened.
2) You’ll probably want to have some control over the Bootstrap button’s sizing, so you should create a custom CSS class. Otherwise you are stuck with Bootstrap’s default sizes (.btn-lg, .btn-sm, or .btn-xs for Bootstrap version 3.3)
3) You cannot nest the div containing the button inside of the div that covers the HTML form. This is because of the opacity setting. Child elements inherit the opacity setting of their parent, so in this case if you were to nest the button inside the div that overlays the form, the button would appear faded. Obviously we don’t want a faded button, we want the opposite effect… a strong and visible button. To achieve this, we need two absolutely positioned div elements, one with the opaque background that blocks all elements on the HTML form, and one with the Saving/Loading message, but on rendering, the button should appear over top of the element blanking out the HTML form.
4) To position the Saving message button in the middle of the HTML window (even if the user re-sizes the window), you can set the top style to 50% and the text-align style to center in the element itself.
5) In the JavaScript, you make the invisible div (display:none;) visible by setting its display to ‘block‘
6) You need to set the z-index of the button’s div slightly higher than the z-index of the opaque disabling div.
7) In the JavaScript, you can simply set the width of the opaque disabling div to 100%, but you need to calculate the height based on if the window is scrolling or not. Use clientHeight if there are no vertical scroll bars, and use scrollHeight if scrolling is enabled.
The Example Code:
Here is the markup you can copy and paste into an example HTML page:
<html> <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css"> <style type="text/css"> .btn-xlarge { padding: 20px 38px; font-size: 22px; line-height: normal; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } </style> <script type="text/javascript"> function showLoadingDiv() { var bcgDiv = document.getElementById("divBackground"); var divWaitForPageLoad = document.getElementById("divWaitForPageLoad"); bcgDiv.style.display = "block"; divWaitForPageLoad.style.display = "block"; if (bcgDiv != null) { if (document.body.clientHeight > document.body.scrollHeight) { bcgDiv.style.height = document.body.clientHeight + "px"; } else { bcgDiv.style.height = document.body.scrollHeight + "px"; } bcgDiv.style.width = "100%"; } setTimeout(function(){ hideLoadingDiv(); }, 5000); } function hideLoadingDiv() { var bcgDiv = document.getElementById("divBackground"); var divWaitForPageLoad = document.getElementById("divWaitForPageLoad"); bcgDiv.style.display = "none"; divWaitForPageLoad.style.display = "none"; } </script> </head> <Body> <div id = "divBackground" style=" position:absolute; top:0px; left:0px; color:white; background-color:#EAF2F9; z-index:9000;opacity: 0.4;filter:alpha(opacity=40); -moz-opacity: 0.8; overflow:hidden; display:none; background: repeating-linear-gradient(45deg, #BAD9F4, #BAD9F4 10px, #EAF2F9 10px, #EAF2F9 15px)"> </div> <div class="container" id="divWaitForPageLoad" style="position:absolute;display:none;z-index:9010;top:50%;text-align: center;"> <button class="btn btn-xlarge btn-warning" id="btnWaitForPageLoad" ><span class="glyphicon glyphicon-refresh"></span> Saving...</button> </div> <input type="button" value="Click me to disable page" onClick="showLoadingDiv();"> </body> </html>