Internet Explorer在window.open和AJAX调用上调用window.onbeforeunload

时间:2009-11-01 21:51:21

标签: ajax internet-explorer window.open onbeforeunload

好的,我已经花了一些时间解决这个问题,这就是我收集的内容:

  1. 如果在IE7中进行AJAX调用并且指定了window.onbeforeunload函数,则会调用onbeforeunload函数。

  2. 如果您尝试使用window.open打开一个新窗口而不会打扰当前窗口,则会调用onbeforeunload。

  3. 有谁知道怎么制止这个?我甚至尝试将变量设置为TRUE并在我的onbeforeunload函数中检查该变量,它仍然无效!我只需要能够为AJAX调用和新窗口调用停止执行该方法。

8 个答案:

答案 0 :(得分:7)

另一种可能更简单的选择是在打开弹出窗口时返回false:

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

这似乎阻止IE认为你离开页面并触发事件。所有其他选择对我来说都不是特别可行。

答案 1 :(得分:3)

好的,我一直有这个问题。我有一个(相当混乱)的工作。

就我而言,我希望有时阻止导航,而不是其他人。

所以,我在窗口设置一个标志,告诉我是否要阻止它。那么你在做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 :(得分:2)

这不是解决方案,而是对任何感兴趣的人的解释。我刚刚在IE 7中运行了一个快速测试,它会在点击链接时触发onebeforeunload事件,除非HREF在同一页面上某处:即除非它包含#。所以我的猜测是,IE工程师认为当有人点击不在页面上其他地方的链接时,他们必须离开页面,在这种情况下页面即将卸载。不用说,这种想法存在明显的问题。

答案 3 :(得分:1)

我认为您只需要在执行任何操作之前取消设置window.onbeforeunload函数,然后在完成后将其重新设置。

我刚刚在IE中禁用该功能。

答案 4 :(得分:1)

我遇到了同样的问题,在我的情况下,所有请求都来自ajax调用,这简化了解决方案,因为当我用标准按钮修复了porblem时,我做了一个递归函数将所有onclick重定向到我的集中函数然后发送钻取点击。 我正在复制ajax调用支持href问题的解决方案。 此解决方案避免返回上一页。将代码放在名为backbutton,js的文件中 任何评论写入mparma@usa.net主题:javascript backbutton

<!--  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;
}

答案 5 :(得分:1)

Sid_M说了一个有效点,我们必须相应地设计我们的应用程序。

为什么选择锚标签&amp;弹出窗口的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>

答案 6 :(得分:0)

你是否尝试在调用window.open之前从“onbeforeunload”事件中删除处理程序?这可以有所帮助,但我从未测试过它。

答案 7 :(得分:0)

这很可能解决您的问题!

因为我遇到了类似的问题而且这样做了!

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

每当我进行Ajax调用或弹出另一个窗口时,我只需将warnRequired设置为false。

另外一件事就是在进行Ajax调用时要注意它是同步的,否则变量可能还没有设置好! (一个讨厌的Gotcha!)