Internet Explorer вызывает window.onbeforeunload для вызовов window.open и AJAX - PullRequest
11 голосов
/ 02 ноября 2009

Хорошо, я потратил некоторое время на эту проблему, и вот что я собрал:

  1. Если вы выполняете AJAX-вызов в IE7, и у вас задана функция window.onbeforeunload, она вызывает функцию onbeforeunload.

  2. Если вы попытаетесь открыть новое окно с помощью window.open БЕЗ нарушения текущего окна, вызывается onbeforeunload.

Кто-нибудь знает, как это остановить? Я даже попытался установить переменную в TRUE и проверить эту переменную в моей функции onbeforeunload, и она все еще не работает! Мне просто нужно иметь возможность остановить выполнение этого метода для вызовов AJAX и вызовов нового окна.

Ответы [ 8 ]

7 голосов
/ 08 ноября 2010

Другой и, возможно, более простой вариант - возвращать false при открытии всплывающего окна:

<a onclick="window.open(...); return false;" href="javascript:;" >my link</a>

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

3 голосов
/ 06 октября 2010

ОК, у меня возникла эта проблема. У меня есть (довольно грязное) решение этой проблемы.

В моем случае я хочу иногда блокировать навигацию, а не другие.

Итак, я устанавливаю флажок в окне, чтобы сказать, хочу ли я заблокировать его. Поэтому, когда вы делаете свой window.open, перед этим выполните «window.allowExit = true», затем в onbeforeunload проверьте для window.allowExit = true.

У меня есть java-скрипт (SHowHelp), который был запущен по ссылке:

<a href="javascript:ShowHelp('argument')" >HERE</a>

onbeforeunload называется ДО ShowHelp, поэтому я использовал onclick для установки флага

<a onclick="window.allowExit = true;" href="javascript:ShowHelp('argument')" >HERE</a>

Гадкий как грех, но, кажется, работает!

2 голосов
/ 08 октября 2010

Это не решение, а объяснение для всех, кто заинтересован. Я только что провел быстрый тест в IE 7, и он запускает событие onebeforeunload при каждом нажатии ссылки, если только HREF не идет где-то на той же странице: то есть, если он не содержит #. Таким образом, я предполагаю, что инженеры IE думали, что когда кто-то нажимает на ссылку, которая не находится где-то еще на странице, то он должен покинуть страницу, и в этом случае страница собирается выгружаться. Само собой разумеется, есть очевидные проблемы с этим мышлением.

1 голос
/ 27 апреля 2012

Сид_М сказал верную точку зрения, с этим дизайном браузера мы должны соответствующим образом спроектировать наше приложение.

Зачем использовать тег привязки и href для всплывающих окон, просто используйте метод onclick в метке или даже тег td и вызовите window.open

Простой пример из одного моего приложения

<td class="popuplink" onMouseOver="this.style.cursor='hand'" onclick="javascript:openMe('img/howitworks.png', 'pndpopup', 600,650)"><u> How it works</u></td>
1 голос
/ 14 июня 2011

У меня была та же проблема, в моем случае все запросы исходят от вызова ajax, это упрощает решение, потому что, когда я исправил проблему с помощью стандартной кнопки, я сделал рекурсивную функцию, чтобы перенаправить весь клик на мою централизованную функцию Правильный щелчок. Я также копирую решение проблемы с поддержкой AJAX. Это решение не позволяет вернуться на предыдущую страницу. Поместите код в файл с именем backbutton, js Любой комментарий пишите на mparma@usa.net с темой: кнопка javascript

<!--  backbutton developed by Manuel Parma 2011-06-10 -->
<!--  email: mparma@usa.net -->
<!--  Add the next line into the <body> section as a first line  -->
<!--  <script type="text/javascript" src="<path>/backbutton.js"></script> -->

<!-- Address used when backtoLogin is 1 or when there is not previous page from site -->
var returningAddress = "http://my returning address"

<!-- Message to display when an external action (back button, forward button, backspace) move without press the application buttons -->
var backButtonMessage = "Using the browser's Back button may cause a loss in data. Please use the Back and Continue buttons at the bottom of the form."

<!-- 0=no / 1=yes (assume per default that the back button will be pressed -->
<!--               and come into action if this was NOT the case)          -->
var backButtonPressed = 1;    

<!--This var when is setted to 1 avoid to captureEvent set backbuttonPressed to 1, otherwise unload event cannot detect the right state of backButtonPressed-->
var onbeforeunloadeventFired = 0;

<!--Indicate to logic back to first page (login) when its value is 1 otherwise the logic back to previous page out of the site-->
var backtoLogin = 0;
var DoPostBackWithOptionsHook = null;
var DoPostBackHook = null;


<!-- Check the previous status -->
if (window.name == ""){
    <!-- When window.name is empty, this is indicating the first call of site -->
    window.name = "L0001";
}
else { 
    if (window.name == "L0000_back"){
        <!-- In this condition the page is returning after a foward button press  -->
        setBackButton(0);
        window.name = "";

        <!-- the system reload the page to clean the data -->
        window.location.href = returningAddress;
    }
    else {
        if (window.name.indexOf("_back") > 4){
            <!-- when the word back is present, the previous call is sending a message that the back button was pressed and the site is going out -->

            <!-- get the internal counter -->
            var sLastValue = modifynamevalue(0);    

            <!-- set the count to go back -->
            var iCountBack = -(sLastValue * 1);
            if (backtoLogin == 1) {iCountBack++;};

            if (window.history.length - 2 < -iCountBack) {
                iCountBack = -(window.history.length - 2);
            }

            <!-- the site is flag that first page needs to reload -->
            window.name = "L0000_back";             
            setBackButton(0);

            <!-- the site is returning to the first page or previous -->
            window.history.go(iCountBack);
        }
        else {
            <!-- increase the internal counter -->
            var sLastValue = modifynamevalue(+1);
            window.name = "L" + sLastValue;
        }
    }
}

<!-- Set the events needed to manage the back and forwar button situations -->

$(document).ready(function(){
    if (typeof(Sys) == "object") {
        Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);

        window.onbeforeunload = onbeforeunloadEvent;
        window.onunload = unloadEvent;
        DoPostBackWithOptionsHook = WebForm_DoPostBackWithOptions;
        WebForm_DoPostBackWithOptions = WebForm_DoPostBackWithOptionsHook;

        doPostBackHook = __doPostBack;
        __doPostBack =  __doPostBackHook;

    }

    });

function WebForm_DoPostBackWithOptionsHook(options) {
    setBackButton(0);
    return DoPostBackWithOptionsHook(options)
}

function __doPostBackHook(eventTarget, eventArgument) {
    if (backButtonPressed == 1) {
        setBackButton(0);
    }
    return doPostBackHook(eventTarget, eventArgument)
} 

function beginRequest(sender, args) {
    setBackButton(0);
    <!-- setting onbeforeunloadeventFired = 1 I take care to avoid anyone changed the Backbutton until endrequest -->
    onbeforeunloadeventFired = 1;
}


function endRequest(sender, args) {
    onbeforeunloadeventFired = 0;
    setBackButton(1);
}

<!-- unload event handler -->
function unloadEvent(evt) {
    <!-- double coundition using onbeforeunloadeventFired == 1 garantee avoid problemas with redirect operations -->
    if ((backButtonPressed == 1) && (onbeforeunloadeventFired == 1)) {
        <!-- decrement the internal counter -->
        var sLastValue = modifynamevalue(-1);
        window.name = "L" + sLastValue + "_back";
    }

    if (DoPostBackWithOptionsHook !== null) {
        WebForm_DoPostBackWithOptions = DoPostBackWithOptionsHook;
    };

    if (doPostBackHook !== null) {
        __doPostBack = doPostBackHook;
    };
}

<!-- on before unload -->
function onbeforeunloadEvent(evt) {
    onbeforeunloadeventFired = 1;
    if (backButtonPressed == 1) {
        return backButtonMessage;
    };
}


<!-- used to set right backButtonPressed-->
function setBackButton(value){
    if (value == 0) {
        backButtonPressed = 0;
    }
    else {
        if (onbeforeunloadeventFired == 0) {
            backButtonPressed = 1;
        }
    }
}


<!-- increment and decrment the internal counter stored into windows.name -->
function modifynamevalue(iIncrement){
    var iCount = (window.name.substring(1, 5) * 1) + iIncrement;

    if (iCount < 0) {
        iCount = 0;
    }

    var sNewValue = iCount.toString();

    sNewValue = "0000".substring(0, 4 - sNewValue.length) + sNewValue;
    return sNewValue;
}
1 голос
/ 06 октября 2010

Я подумал, что вам нужно просто сбросить функцию window.onbeforeunload, прежде чем что-то делать, а затем вернуть ее обратно, когда вы закончите.

Я только что отключил эту функцию в IE.

0 голосов
/ 02 сентября 2011

Это вполне может решить вашу проблему!

Потому что у меня была похожая проблема, и это помогло!

window.onbeforeunload = warnFunction;
var warnRequired = true;
function warnFunction () {
    if (warnRequired) return ("Please Stay! Don't go!");
    return ;
}

И всякий раз, когда я делаю Ajax-вызов или открываю другое окно, я просто устанавливаю warnRequired в false.

Еще одна вещь, просто помните, что при вызове Ajax он синхронизируется, иначе переменная еще не была установлена! (Гадкий Готча!)

0 голосов
/ 19 июля 2010

вы пытались удалить обработчик из события "onbeforeunload" перед вызовом window.open? Это может помочь, но я никогда не проверял это.

...