09 March 2011

IE window.showModalDialog() - Cross Browser solution

Hello,

QUESTION: How to make window.showModalDialog() work on cross browser? or at least how to do something similar? with arguments, return value and window.close()?

ANSWER: There is no simple way to do that.

ATTENTION: dialogArguments will be lost if the page inside the popup will do a postback. For a better solution see my new version - click here.

First of all window.showModalDialog() function is something which works only on Internet Explorer and in the best case this command will open a new small window on some browsers, however this window is far from a modal window.

If you still need to have the same functionality as window.showModalDialog(), to pass some parameters / arguments to the page inside the popup and then return some values back from that page in the parent page, and also have the ability to close the popup from the inside of the popup then this article is for you.

Here I have created a modal popup, using jQuery, which gives you the ability to pass arguments to the page inside the popup almost in the same way as you would pass it through showModalDialog().



This is basically a jQuery dialog which of which content is actually a iframe, the iframe will open the url that you want. The title of the popup will be the same as the title from the page.

I have created this like a jQuey plugin, here is the code.

Code:
(function($) {
    // START of plugin definition
    $.fn.showModalDialog = function(options) {

        // build main options and merge them with default ones
        var optns = $.extend({}, $.fn.showModalDialog.defaults, options);

        // create the iframe which will open target page
        var $frame = $('<iframe />');
        $frame.attr({
            'src': optns.url,
            'scrolling': optns.scrolling
        });

        // set the padding to 0 to eliminate any padding, 
        // set padding-bottom: 10 so that it not overlaps with the resize element
        $frame.css({
            'padding': 0,
            'margin': 0,
            'padding-bottom': 10
        });

        // create jquery dialog using recently created iframe
        var $modalWindow = $frame.dialog({
            autoOpen: true,
            modal: true,
            width: optns.width,
            height: optns.height,
            resizable: optns.resizable,
            position: optns.position,
            overlay: {
                opacity: 0.5,
                background: "black"
            },
            close: function() {
                // save the returnValue in options so that it is available in the callback function
                optns.returnValue = $frame[0].contentWindow.window.returnValue;
                optns.onClose();
            },
            resizeStop: function() { $frame.css("width", "100%"); }
        });

        // set the width of the frame to 100% right after the dialog was created
        // it will not work setting it before the dialog was created
        $frame.css("width", "100%");

        // pass dialogArguments to target page
        $frame[0].contentWindow.window.dialogArguments = optns.dialogArguments;
        // override default window.close() function for target page
        $frame[0].contentWindow.window.close = function() { $modalWindow.dialog('close'); };

        $frame.load(function() {
            if ($modalWindow) {
                
                var maxTitleLength = 50; // max title length
                var title = $(this).contents().find("title").html(); // get target page's title

                if (title.length > maxTitleLength) {
                    // trim title to max length
                    title = title.substring(0, maxTitleLength) + '...';
                }

                // set the dialog title to be the same as target page's title
                $modalWindow.dialog('option', 'title', title);
            }
        });

        return null;
    };

    // plugin defaults
    $.fn.showModalDialog.defaults = {
        url: null,
        dialogArguments: null,
        height: 'auto',
        width: 'auto',
        position: 'center',
        resizable: true,
        scrolling: 'yes',
        onClose: function() { },
        returnValue: null
    };
    // END of plugin
})(jQuery);

// do so that the plugin can be called $.showModalDialog({options}) instead of $().showModalDialog({options})
jQuery.showModalDialog = function(options) { $().showModalDialog(options); };


Bowser Support






To open the modal dialog: $.showModalDialog (options); OR $().showModalDialog(options);
I have created the first one to be easier to call and for programmer to understand that this will not change or use any collection of elements.

Options:
url - String: the url of the page to be opened inside the popup (Default: null;);
dialogArguments - Object: the arguments which you need to pass to the target page (Default: null);
height - Number: the height in pixels of the modal dialog (Default: 'auto';);
width Number: the width in pixels of the modal dialog (Default: 'auto');
position - String, Array: Specifies where the dialog should be displayed (Default: 'center'). Possible values:
               1) a single string representing position within viewport: 'center', 'left', 'right', 'top', 'bottom'.
               2) an array containing an x,y coordinate pair in pixel offset from left, top corner of viewport (e.g. [350,100])
               3) an array containing x,y position string values (e.g. ['right','top'] for top right corner).
resizable - Boolean: indicates if user will be able to resize the modal dialog or not (Default: true);
scrolling - String: indicates if user will be able to scroll the content inside the modal dialog or not (Default: 'yes', Possible values: 'yes', no');
onClose - It is an event - this is the action that should be performed when the dialog will be closed (Default: null).

To get the value of the arguments from the target window - you just need to write in the same way as you would do for window.showModalDialog() - window.dialogArguments.
To set the returnValue - window.returnValue.
To close the dialog - window.close().

Below is an example of how to use this plugin.

Code:
function showJQ() {
    $.showModalDialog({
        url: 'TestPage.htm',
        height: 400,
        width: 500,
        resizable: true,
        scrolling: 'no',
        dialogArguments: 'Arguments Test',
        onClose: processReturnedValue
    });
}

function processReturnedValue() {
    alert(this.returnValue);
}

Here is an example of a target page, which will be shown in the popup, it demonstrates how to work with the arguments, returnValue and window.close():

Code:
<html>
<head>
    <title>Test This Window</title>
</head>
<body>
<script type="text/javascript">
    function closeMe() {
        window.returnValue = 'The Return Value + ' + window.dialogArguments;    
        window.close();
    }
</script>
<input type="button" onclick="closeMe();" value="Close Popup" />
</body>
</html>

I hope this code will help a lot of people, because it is easy to used and because it will work on different browsers.

Any questions or suggestions? leave a comment.

4 comments:

Firdaus Islam said...

HI, first of all, id like to thank you for sharing your code.

I want to ask about the problem when using your script for IE9, it says :

SCRIPT438: Object doesn't support property or method 'dialog'
showModalDialog.js, line 24 character 9

// create jquery dialog using recently created iframe
var $modalWindow = $frame.dialog({})

any thought?

Roman Gherman said...

Hi Firdaus,

You probably did not include Jquery UI that contains the dialog function.

Unknown said...

Hi,

Thanks a lot for sharing this piece of code, it's just what I was looking for :). I'm having some problems to get the dialogArguments property in the target page. I was debugging and the property is correctly set in this line:

$frame[0].contentWindow.window.dialogArguments = optns.dialogArguments;

But, when I try to get it in the target page using window.dialogArguments as you do in the example I get an undefined. Any clue what could I be missing?

Thanks in advance!

Anonymous said...

Hello,

Well I tried your above code , but I am not able to open popup (dialog)


It throws this error on console :-
Uncaught TypeError: Cannot read property 'document' of null

Post a Comment

your thoughts are welcome:

Need more? Leave comments and subscribe to my blog.

.