This article explains how to build and use a modal popup component for Web Runtime widgets.
Modal popup windows or messages are useful to display important information to the user, blocking the rest of the Widget interface until the popup is disposed, typically by pressing a button.
Contents |
The Popup component presented in this article can be used by following these steps:
<script language="javascript" type="text/javascript" src="Popup.js"></script>
Since the image will be stretched both horizontally and vertically, the image size is not a problem.
var popup = new Popup(
"This is just a <strong>sample popup</strong>",
"OK",
null,
"Cancel",
null);
popup.show();
Arguments for the Popup constructor are the following:
Sample CSS rules, used in this article, are the following:
.popup {
border: 3px solid #336699;
padding: 4px;
background: white;
text-align:center;
}
.popup_buttons {
overflow: auto;
}
#popup_button_ok, #popup_button_cancel {
border: 1px solid #336699;
background-color: gray;
color:white;
min-width: 50px;
text-align:center;
padding: 10px;
}
#popup_button_ok:hover, #popup_button_cancel:hover {
background-color: #6699cc;
}
#popup_button_ok {
float: left;
margin-left: 10px;
background-image: url("images/accept.png");
background-position: left center;
padding-left: 16px;
background-repeat: no-repeat;
}
#popup_button_cancel {
float: right;
margin-right: 10px;
background-image: url("images/cancel.png");
background-position: left center;
padding-left: 20px;
background-repeat: no-repeat;
}
The Popup component is structured as shown by the following picture.
So, once the WRT widget needs to show a Popup instance, the component will perform these steps:
Since the image will cover the whole Widget user interface, user interactions will be forbidden until the popup, and so the image cover, will be disposed.
Now, let's see the component implementation.
This Popup component built in this article has customizable features:
The Popup constructor allows to set all these properties through its arguments:
function Popup(popupHtml, okButtonText, okButtonHandler, cancelButtonText, cancelButtonHandler)
{
/* HTML content to be shown inside the popup */
this.popupHtml = popupHtml;
/* text for the ok button */
this.okButtonText = okButtonText;
/* text for the cancel button */
this.cancelButtonText = cancelButtonText;
/* handler function for the ok button */
this.okButtonHandler = okButtonHandler;
/* handler function for the cancel button */
this.cancelButtonHandler = cancelButtonHandler;
/* page cover DOM element */
this.coverElement = null;
/* popup DOM element */
this.popupElement = null;
}
The last 2 defined properties will hold references to the image cover and popup DOM elements, respectively.
Before building the popup DOM structure, some properties are defined in order to allow easier styling and customization of Popup visual appearance.
/* CSS class applied to the main popup element */
Popup.MAIN_CSS_CLASS = 'popup';
/* CSS class applied to popup content */
Popup.TEXT_CSS_CLASS = 'popup_text';
/* CSS class applied to popup buttons' container */
Popup.BUTTONS_CSS_CLASS = 'popup_buttons';
/* path of the image used to opacize the widget */
Popup.COVER_IMAGE_SRC = 'images/page_cover.png';
/* element ID of the OK button */
Popup.OK_BUTTON_ID = 'popup_button_ok';
/* element ID of the CANCEL button */
Popup.CANCEL_BUTTON_ID = 'popup_button_cancel';
/* minimum margin of the popup from screen boundaries */
Popup.MARGIN = 20;
/* z-index to be used for the popup DOM element */
Popup.zIndex = 10000;
The Popup DOM structure is built on the fly when the Widget needs to display it. So, all the job is done by the show() method:
Popup.prototype.show = function(beforeShowHandler)
{
/* calculate the width and height to be covered */
var bodyHeight = Math.max(document.body.offsetHeight, window.innerHeight);
var bodyWidth = document.body.offsetWidth;
/* build the cover that will opacize the widget's content */
var coverElement = document.createElement('img');
coverElement.src = Popup.COVER_IMAGE_SRC;
coverElement.style.position = 'absolute';
coverElement.style.width = '100%';
coverElement.style.height = bodyHeight + 'px';
coverElement.style.top = '0px';
coverElement.style.left = '0px';
coverElement.style.zIndex = Popup.zIndex - 1;
this.coverElement = coverElement;
/* append the cover element to the document's body */
document.body.appendChild(coverElement);
/* now, build the popup DOM element */
var popupElement = document.createElement('div');
popupElement.style.position = 'absolute';
popupElement.style.width = (bodyWidth - 2 * Popup.MARGIN) + 'px';
popupElement.style.left = (document.body.scrollLeft + Popup.MARGIN) + 'px';
popupElement.style.zIndex = Popup.zIndex;
popupElement.className = Popup.MAIN_CSS_CLASS;
this.popupElement = popupElement;
/* build the DOM element that contains the popup content */
var textElement = document.createElement('div');
textElement.className = Popup.TEXT_CSS_CLASS;
textElement.innerHTML = this.popupHtml;
popupElement.appendChild(textElement);
/* add the ok and cancel buttons */
var buttonsContainer = document.createElement('div');
buttonsContainer.className = Popup.BUTTONS_CSS_CLASS;
popupElement.appendChild(buttonsContainer);
var okButton = document.createElement('div');
okButton.id = Popup.OK_BUTTON_ID;
okButton.innerHTML = this.okButtonText;
buttonsContainer.appendChild(okButton);
var self = this;
okButton.onclick = function()
{
self.okButtonPressed();
}
if(this.cancelButtonText != null)
{
var cancelButton = document.createElement('div');
cancelButton.id = Popup.CANCEL_BUTTON_ID;
cancelButton.innerHTML = this.cancelButtonText;
buttonsContainer.appendChild(cancelButton);
cancelButton.onclick = function()
{
self.cancelButtonPressed();
}
}
if(beforeShowHandler)
beforeShowHandler(popupElement);
/* finally, append the popup element to the document's body */
document.body.appendChild(popupElement);
/* let's center the popup */
var popupTop = Math.max(
(document.body.scrollTop + (window.innerHeight - popupElement.offsetHeight) / 2),
document.body.scrollTop
);
popupElement.style.top = popupTop + 'px';
}
The show() method accepts an optional function handler as argument: if passed, it will be called just before the Popup DOM element is actually shown, in order to allow further customization of the component itself.
The steps performed by the show() method are:
The following methods are used to manage user interaction for the OK and CANCEL buttons, respectively. If custom handlers were defined though the component's constructor, they'll be called as well.
/**
* Function called when the popup CANCEL button is pressed
*/
Popup.prototype.cancelButtonPressed = function()
{
this.hide();
if(this.cancelButtonHandler != null)
this.cancelButtonHandler();
}
/**
* Function called when the popup OK button is pressed
*/
Popup.prototype.okButtonPressed = function()
{
this.hide();
if(this.okButtonHandler != null)
this.okButtonHandler();
}
Once the user has seen the popup, and wants to dispose it (through one of the OK and CANCEL button), the hide() method will be called to actually dispose the component:
/**
* Function to hide the popup
*/
Popup.prototype.hide = function()
{
this.popupElement.parentNode.removeChild(this.popupElement);
this.coverElement.parentNode.removeChild(this.coverElement);
this.popupElement = null;
this.coverElement = null;
}
The following files are available for download: