sexta-feira, 17 de julho de 2015

Custom ShowModalDialog with JQuery!

Já é de conhecimento de todos (ou da maioria) que a API [window.showModalDialog] foi descontinuada pelo Browser Chrome, a partir da versão 37 - Disabling showModalDialog.

Com isto muitos WebSites simplesmente não executam mais este recurso neste browser.

Como ele é usado extensamente, o que fazer então em substituição ao depreciado showModalDialog? Vamos criar um próprio, usando a tecnologia JQuery!

A função ShowModalDialog


if (typeof (GT) == "undefined") { GT = {}; }

GT.Functions = {
    ShowModalDialog: function (content, parent, width, height, bkgImage, callbackFn) {
        var divTag = '<div id="divDialog" ';
        divTag += 'style="border: 6px solid gray; overflow:hidden; box-shadow: 1px 1px 5px #333; ">';
 
        if (bkgImage) {
            divTag += '<div id="divDialogLoading" ';
            divTag += 'style="width:' + width + 'px; height:' + height + 'px; ';
            divTag += 'background: white url(' + bkgImage + ') no-repeat center;" >';
            divTag += '</div>';
        }
 
        divTag += '<iframe id="frameDialog" frameBorder="0" scrolling="no" ';
        divTag += 'src="' + content + '" ';
        divTag += 'style="width:100%;" ';
 
        divTag += '>';
        divTag += '</iframe>';
 
        divTag += '</div>';
 
        var div = null;
        var $JQ = null;
 
        if (parent != null) {
            var $JQ = parent.jQuery.noConflict();
            parent.window.defer = $JQ.Deferred();
            div = $JQ(divTag).appendTo("body");
        }
        else {
            $JQ = jQuery.noConflict();
            window.defer = $JQ.Deferred();
            div = $JQ(divTag);
        }
 
        div.append('<style type="text/css"> \
        .ui-widget-overlay { \
            position: absolute; \
            top: 0; \
            left: 0; \
            width: 100%; \
            height: 100%; \
            background: #aaaaaa;\
            opacity: 0.3; \
            } \
        .ui-front { \
            z-index: 100; \
            } \
        </style>');
 
        div.dialog({
            position: {
                my: "center",
                at: "center",
                of: div,
                within: div
            },            
            autoOpen: false,
            closeOnEscape: false,
            height: height,
            width: width,
            modal: true,
            open: function () {
                $JQ('#frameDialog').on("load", function () {
                    $JQ("#divDialogLoading").hide();
                    this.height = div.height();
                });
            },
            close: function () {
                if (callbackFn) callbackFn();
            }
        });
 
        div.dialog('open');
 
        return (parent != null ? parent.window.defer.promise() : window.defer.promise());
 
    }
};


Algumas considerações

Em si a função é simples pois utiliza o componente JQuery UI Dialog para mostrar um diálogo para o usuário. O mais importante é o uso do método [$.Deferred()] e o retorno da função, que utiliza o método [promise].

É justamente isto que garante que o diálogo se comporte como a API window.showModalDialog, trabalhando de forma síncrona com o resto do seu código JavaScript.

Importante: Se você pretende usar as versões mais recentes (a partir da 1.7.x) do JQuery UI Dialog em uma página ASPX, não se esqueça de usar a seguinte declaração no documento de sua página

<!DOCTYPE html>

Isto garante que o diálogo vai ser posicionado corretamente (no caso da nossa função, no centro da página).

Como devo usar o método

Veja abaixo dois exemplos de uso do método. O primeiro uso é básico. O segundo é interessante porque permite ao desenvolvedor executar o método a partir de uma página dentro de um [iframe].


var url = "http://MeuSite/MinhaPagina.aspx?param=test";

GT.Functions.ShowModalDialog(
 url,
 null,
 470,
 470,
 null,
 function result() {
  window.defer.then(
   function (result) {
    if (result)
    {
     // TRABALHA COM O RETORNO DA PÁGINA (url) PASSADA POR PARÂMETRO
    }
   });
 });



var url = "http://MeuSite/MinhaPagina.aspx?param=test";
var _parentW = (document.parentWindow ? document.parentWindow.parent : document.defaultView.parent);
var $jParent = _parentW.jQuery.noConflict();

GT.Functions.ShowModalDialog(
 url,
 _parentW,
 470,
 470,
 null,
 function result() {
  _parentW.window.defer.then(
   function (result) {
    if (result)
    {
     // TRABALHA COM O RETORNO DA PÁGINA (url) PASSADA POR PARÂMETRO
    }
   });
 });


E por fim precisamos retornar um valor para o método através da nossa página de exemplo (MinhaPagina.aspx). Note novamente que temos um exemplo de retorno simples e outro na qual a página ASPX se encontra dentro de um [iframe]


function CloseDialog()
{
 window.defer.resolve("VALOR PARA RETORNAR");
 $("#divDialog").dialog("close");
 $("#divDialog").dialog("destroy");
 $("#divDialog").remove();
}



function CloseDialog()
{
 var _parentW = (document.parentWindow ? document.parentWindow.parent : document.defaultView.parent);
 _parentW.window.defer.resolve("VALOR PARA RETORNAR");
 var $jParent = _parentW.jQuery.noConflict();
 $jParent("#divDialog").dialog("close");
 $jParent("#divDialog").dialog("destroy");
 $jParent("#divDialog").remove();
}


Refs:
JQuery UI Dialog
JQuery Deferred API

Cheers!!