Вернуть значение из window.open

Недавно мы обнаружили, что Chrome больше не поддерживает window.showModalDialog, что проблематично, поскольку наше корпоративное приложение использует этот метод.

Существует, по-видимому, краткосрочный обходной путь, который позволяет вам восстановить showModalDialog, но он включает в себя изменение реестра, что является слишком сложным (и рискованным) для нашего среднего пользователя. Поэтому я не большой поклонник этого обходного пути.

Долгосрочное решение, очевидно, состоит в том, чтобы удалить все вызовы этого устаревшего метода и заменить их удобным плагином jQuery (например, плагином Skinny Modal Dialog для VistaPrint. Кстати, другие предложения приветствуются).

Типичный сценарий, который мы используем в модальном диалоговом окне, заключается в том, чтобы запросить у пользователя подтверждение "Да / Нет" перед выполнением действия, которое нельзя отменить, попросить пользователя согласиться с условиями и положениями, прежде чем продолжить, и т. Д. Как правило, событие onclick для "Да" или кнопка "ОК" в модальном диалоге выглядит так:

window.returnValue = true;
window.close();

Точно так же кнопка "Отмена" или "Нет" выглядит следующим образом:

window.returnValue = false;
window.close();

Тот факт, что мы можем вернуть значение из диалогового окна, очень удобен, потому что он позволяет "родительскому" окну получать уведомление о том, нажал ли пользователь кнопку "ОК" или "Отмена" следующим образом:

var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
    ... proceed ...
}

Последнее, что я хочу упомянуть о showModalDialog, - это то, что он отлично работает, даже если документ, отображаемый в диалоговом окне, принадлежит другому домену. Мы очень часто запускаем наш javascript с http://the-client.com/ но веб-страница "Условия предоставления услуг" с http://the-enterprise-vendor.com/

Мне нужно временное решение, которое я могу развернуть как можно скорее, пока мы работаем над долгосрочным решением. Вот мои критерии:

  • минимальное изменение кода в существующем JavaScript
  • всплывающее окно должно иметь возможность вернуть значение "родителю". Обычно это значение является логическим, но это может быть любой простой тип (например, string, int и т. Д.)
  • решение должно работать, даже если URL-адрес контента находится в другом домене

Вот что у меня так далеко:

1) Добавьте следующий метод в мой JavaScript:

function OpenDialog(url, width, height, callback)
{
    var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
    var timer = setInterval(function ()
    {
        if (win.closed)
        {
            clearInterval(timer);
            var returnValue = win.returnValue;
            callback(returnValue);
        }
    }, 500);
}

Как вы можете видеть в этом методе, я пытаюсь сделать всплывающее окно максимально похожим на диалог, скрывая меню и панель инструментов, я устанавливаю время каждые 500 миллисекунд, чтобы проверить, было ли окно закрыто пользователем и если это так, получить returnValue и вызвать обратный вызов.

2) замените все вызовы showModalDialog следующим:

OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
    if (termsOfServiceAccepted)
    {
        ... proceed ....
    }
});

Четвертым параметром метода является обратный вызов, где я проверяю, нажал ли пользователь кнопку "ОК", прежде чем позволить ей продолжить.

Я знаю, что это длинный вопрос, но в основном это сводится к:

  1. Что вы думаете о предложенном мной решении?
  2. В частности, вы думаете, я смогу получить returnValue из окна, которое было открыто с помощью window.open?
  3. Любая другая альтернатива, которую вы можете предложить?

1 ответ

Решение

У меня есть две идеи, которые могут вам помочь, но первая связана с CORS, поэтому вы не сможете использовать ее из разных доменов, по крайней мере, вы сможете получить доступ к обеим службам и настроить их.

ПЕРВАЯ ИДЕЯ:

Первый связан с этим нативным API. Вы можете создать в родительском окне глобальную функцию, подобную этой:

window.callback = function (result) {
    //Code
}

Как видите, он получает аргумент результата, который может содержать нужное вам логическое значение. Вы можете открыть всплывающее окно, используя ту же старую функцию window.open (url). Обработчик события всплывающего окна может выглядеть так:

function() {
    //Do whatever you want.
    window.opener.callback(true); //or false
}

ВТОРАЯ ИДЕЯ: решает проблему

Другая идея, которую я получил, состоит в том, чтобы использовать этот другой собственный API, чтобы вызвать событие в родительском окне, когда всплывающее окно разрешается (более известный как обмен сообщениями между документами). Так что вы можете сделать это из родительского окна:

window.onmessage = function (e) {
    if (e.data) {
        //Code for true
    } else {
        //Code for false
    }
};

Таким образом, вы прослушиваете любое опубликованное сообщение в этом окне и проверяете, являются ли данные, прикрепленные к сообщению, истинными (пользователь нажимает "ОК" во всплывающем окне) или ложными (пользователь нажимает "Отмена" во всплывающем окне).

Во всплывающем окне вы должны опубликовать сообщение в родительском окне, добавив значение true или false, когда соответствует:

window.opener.postMessage(true, '*'); //or false

Я думаю, что это решение идеально соответствует вашим потребностям.

РЕДАКТИРОВАТЬ Я написал, что второе решение было также связано с CORS, но копая глубже, я понял, что обмен сообщениями между документами не привязан к CORS

Другие вопросы по тегам