Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

Pure HTML5/CSS3/JS Modal Dialog MsgBox in .NET Style

5.00/5 (8 votes)
13 Oct 2017CPOL4 min read 18.4K   419  
A small JavaScript module to create a modal dialog box or user input box in the familiar .NET style

Introduction

When developing a planimeter application on my VeeTools website, there was the need for a modal user input box setting the scale for a certain map image. Modal windows in an HTML application are familiar (for example, see How TO - CSS/JS Modal, but I missed the .NET MsgBox() functionality with the ability to Ok, Apply or Cancel and to get an input value from the user. I decided to make a small module which can be inserted in any existing JavaScript namespace.

The Basics...

In the source code, you will find three files: dialogbox.html, dialogbox.js and dialogbox.css. I will not discuss the dialogbox.css here (you can alter the style of the dialogs to your own liking) apart from pointing out that it makes use of flex panels I describe in an earlier tip/trick: Pure HTML/CSS/JS Panel and Splitcontainer in .NET style.

Example 1

Image 1

The dialogbox.html file contains a simple interface to test out the dialog box and some of the options. The HTML part is a straightforward collections of input and select elements. The button at the bottom calls the function cbGetDialog() in the <script> part of the HTML code snippet below. This function collects all the user inputs and calls dialog.msgBoxGet() from the module to build and return the dialog. Subsequently, the returned dialog is run with module function dialog.msgBoxShow().

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="UTF-8">
    <title>VeeTools DialogBox</title>
    <!-- only external reference to font-awesome for the dialog icons  -->
    <link rel="stylesheet" 
     href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
    <!-- local includes  -->
    <script src="./dialogbox.js"></script>
    <link rel="stylesheet" href="./dialogbox.css" type="text/css">
</head>

<body>
    <div class="" style="">
        <div><label>DialogBox title:</label><input id="title" 
        value="Hello" placeholder="dialog title..." 
        style="position:absolute;left:150px;width:200px;">
        </input></div><br>
        <div><label>DialogBox message:</label><input id="msg" value="World<br>
        The dialog.msgBox in its simplest form..." placeholder="dialog message..." 
        style="position:absolute;left:150px;width:200px;"></input></div><br>
        
        <!-- etc... for all divs look at the zipped html file --> 

        <div><button onclick="cbGetDialog()">Show dialog</button></div>
    </div>
</body>

<script>
    /* example 1 */
    function cbGetDialog(){
        //get the title & msg
        var ttl = document.getElementById("title").value

        //get the message, the msg is split up in <p>'s if there is a <br> in the input value
        var msg = document.getElementById("msg").value 

        //build the dialog
        var dlg = mymod.dialog.msgBoxGet(ttl,msg)

        //run the dialog
        mymod.dialog.msgBoxShow(dlg)
    }
</script>
</html>

Example 2

So far, nothing too difficult. Let's turn the simple message dialog into a user input dialog by changing the following options: dlgStyle, dlgButtons, dlgOkLabel, dlgInputBox and dlgInputBoxCallback, shown in the figure below:

Image 2

In the second example, the <script> part of the file dialogbox.html will look like this:

HTML
<script>
    /* example 2 */
    function cbGetDialog(){
        //get the title
        var ttl = document.getElementById("title").value
        
        //get the message, the msg is split up in <p>'s if there is a <br> in the input value
        var msg = document.getElementById("msg").value
        
        //get the dialog style
        var stl = document.getElementById("optstyle").value
        
        //get the dialog buttons
        var bts = document.getElementById("optbuts").value
        
        //get the buttons alternative labels
        var labok = document.getElementById("labbutok").value
        
        //get the input field checkbox, it should be turned on
        var inpfield = document.getElementById("chkinputfield").checked
        
        //get the input field callback function
        var inpcb = document.getElementById("cbinputfield").value
        if (!inpcb || inpcb=="") inpcb = null
        
        //build the dialog
        var dlg = mymod.dialog.msgBoxGet(ttl,msg,{
            dlgStyle:stl,
            dlgButtons:bts,
            dlgOkLabel:labok,
            dlgInputBox: inpfield,
            dlgInputBoxCallback: window[inpcb],
        })
        //run the dialog
        mymod.dialog.msgBoxShow(dlg)
    }
    
    function cbInputValue(val){
        //if the input field option has been checked this script should return the value entered
        var dlg = mymod.dialog.msgBoxGet("Input result","Input value returned="+val)
        mymod.dialog.msgBoxShow(dlg)
    }
</script>

Note that the callback processing the user input is specified in cbinputfield element and named cbInputValue which should correspond to an existing function. In this case, the function is defined in the HTML file <script> part and therefore the callback is passed as a property of the window by dlgInputBoxCallback: window[document.getElementById("cbinputfield").value]. This is not the most elegant way by using the global stack, but used here for practical purposes. A more proper way inside a namespace would be dlgInputBoxCallback: mymod.myfunction. The callback function cbInputValue in turn creates a new (simple) dialog box returning the value the user has entered.

Example 3

The third example is overriding the default actions of the dialog box. By changing the <script> part of the file dialogbox.html to the following:

HTML
<script>
    /* example 3 */
    function cbGetDialog(){
        //build the dialog with predefined values and overriding the default actions
        var dlg = mymod.dialog.msgBoxGet("A nice app","Go on with this?",{
            dlgStyle:"question",
            dlgButtons:"okcancel",
            dlgCallbackOk:function(){cbGetDialogResult(true)},
            dlgCallbackCancel:function(){cbGetDialogResult(false)},
            dlgOkLabel:"Yes",
            dlgCancelLabel:"Stop!",
            dlgInputBox: false,
        })

        //run the dialog
        mymod.dialog.msgBoxShow(dlg)
    }
    
    function cbGetDialogResult(val){
        var dlg = mymod.dialog.msgBoxGet("A nice app","GoOn="+val)
        mymod.dialog.msgBoxShow(dlg)
    }
</script>

The resulting dialog box from function cbGetDialogResult will either show true or false depending on the button pushed:

Image 3

Note that in the above example, I can simply define an anonymous function(){cbGetDialogResult()} for the callback functions since their names are not a var.

Example 4

The last example shows how a user element can be added to the dialog box. As an example, I will add the image (included in the source code): amsterdam_1836.jpg. The <script> part of the file dialogbox.html looks like this:

HTML
<script>
    function cbGetDialog(){
        //make a div with the image
        var dvi = document.createElement("div")
        var img = document.createElement("img")
        img.setAttribute("src","./amsterdam_1836.jpg")
        img.setAttribute("width","100%")
        img.setAttribute("height","100%")
        dvi.onclick = function(){var dlg = mymod.dialog.msgBoxGet("That's All","Folks");
                      mymod.dialog.msgBoxShow(dlg)}
        dvi.appendChild(img)
        
        //build the dialog with predefined values and the custom element
        var dlg = mymod.dialog.msgBoxGet("A nice image","Of Amsterdam in 1836",{
            dlgCustElement:dvi
        })

        //run the dialog
        mymod.dialog.msgBoxShow(dlg)
    }
</script>

The result is shown below. If you click on the image, you'll get yet another dialog box (see the dvi.onclick).

Image 4

And the Details...

The dialog module simply extends any existing JavaScript module (called mymod in this example) and creates a dialog namespace. The module exposes only two public functions (see source code file dialogbox.js). For the contents of the local functions, refer to the source code.

JavaScript
'use strict';

var mymod = mymod || {};

mymod.dialog = (function() {
    var _exposed = {
        //global methods
        msgBoxGet: msgbxGet,
        msgBoxShow: msgbxShow,
    }

    //globally exposed functions
    function msgbxGet(title,msg,options) {...}
    
    function msgbxShow(msgbox) {...}
    
    //local functions
    function getIcon(dlgstl){...}
    
    function getDialogButton(txt,tbindx,lab){...}
    
    function splitMsg(msg){...}
    
    function oninputKeydown(e,clb,dlg){...}
    
    function ondlgKeydown(e,okclb,dlg){...}
    
    //helper functions not really belonging to the core of the module
	function setElmStyle(elm,props) {...}

    return _exposed;

})(mymod.dialog || {});

Functions Reference and Usage

Function msgBoxGet() constructs a dialogbox with a title and a message and optionally sets dialog style and function parameters. The function returns an HTML element.

Syntax<mod_name>.dialog.msgBoxGet(title, message, {options})
ReturnHTML element
ArgumentsTypeDescription
titleStringTitle of the dialog
messageStringThe message displayed. The message is split up into paragraphs based on the occurrence of '\n' character or the <br> tag
optionsObjectSee below
OptionsTypeDescription
dlgStyleStringStyle of the dialogbox. Can be any of info, exclamation, warning, question, error or none. The dlgStyle also sets the font-awsome icon to use for the dialog.
dlgButtonsStringButtons to show. Can be any of ok, okcancel, okapplycancel.
dlgCallbackOkFunctionFunction to call when the Ok button is clicked. Default action closes the dialog. Any supplied function is executed before the default action. Can be null.
dlgCallbackApplyFunctionFunction to call when the Apply button is clicked. Default action is null. Can be null.
dlgCallbackCancelFunctionFunction to call when the Cancel button is clicked. Default action closes the dialog. Any supplied function is executed before the default action. Can be null.
dlgOkLabelStringOverriding Ok button label.
dlgApplyLabelStringOverriding Apply button label.
dlgCancelLabelStringOverriding Cancel button label.
dlgInputBoxBooleanWhen true shows an input value box. The input value is passed to the dlgInputBoxCallback.
dlgInputBoxCallbackFunctionFunction to call when input value is returned (by either Ok or Return). This function overrides any function specified for dlgCallbackOk or dlgCallbackApply.
dlgCustElementHTML elementCustom user element to be added after the message (and input box if checked). Element should include its own style and callbacks.

Function msgBoxShow() shows a previously constructed dialog box while preventing the main app from receiving input (keyboard, mouse events, etc.):

Syntax<mod_name>.dialog.msgBoxShow(dlgBox)
Returntrue/false
ArgumentsTypeDescription
dlgBoxHTML elementA dialog box created by msgBoxGet()

History

  • October 2017: First published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)