window.focus() 在谷歌浏览器中不起作用

IT技术 javascript google-chrome cross-browser dom-events
2021-02-21 11:53:55

只是想知道谷歌浏览器是否会window.focus()在某个时候支持当我的意思是支持时,我的意思是让它发挥作用。对它的调用不会失败,它只是什么都不做。所有其他主流浏览器都没有这个问题:FireFox、IE6-IE8 和 Safari。

我有一个用于管理浏览器窗口的客户端类。当我第一次创建一个窗口时,窗口成为焦点,但随后尝试将焦点移到窗口上不起作用。

据我所知,这似乎是一项安全功能,可以避免烦人的弹出窗口,而且它似乎不是 WebKit 问题,因为它可以在 Safari 中使用。

我知道有人提出的一个想法是关闭窗口然后重新打开它,但这是一个可怕的解决方案。谷歌搜索表明,我似乎不是唯一对此感到沮丧的人。

为了 100% 清楚,我的意思是新窗口,而不是选项卡(选项卡不能从我读过的内容中获得焦点),并且所有打开的窗口都在同一个域中。

除了我上面提到的坏主意之外,还有其他想法和解决方法吗?

Chromium 项目中记录了一个关于此的错误,请在此处查看感谢您发布Rich

MyCompany = { UI: {} }; // Put this here if you want to test the code. I create these namespaces elsewhere in code.

MyCompany.UI.Window = new function() {
    // Private fields
    var that = this;
    var windowHandles = {};

    // Public Members
    this.windowExists = function(windowTarget) {
        return windowTarget && windowHandles[windowTarget] && !windowHandles[windowTarget].closed;
    }

    this.open = function(url, windowTarget, windowProperties) {
        // See if we have a window handle and if it's closed or not.
        if (that.windowExists(windowTarget)) {

            // We still have our window object so let's check if the URLs is the same as the one we're trying to load.
            var currentLocation = windowHandles[windowTarget].location;

            if (
                (
                    /^http(?:s?):/.test(url) && currentLocation.href !== url
                )
                    ||
                (
                    // This check is required because the URL might be the same, but absolute,
                    // e.g. /Default.aspx ... instead of http://localhost/Default.aspx ...
                    !/^http(?:s?):/.test(url) &&
                    (currentLocation.pathname + currentLocation.search + currentLocation.hash) !== url
                )
            ) {
                // Not the same URL, so load the new one.
                windowHandles[windowTarget].location = url;
            }

            // Give focus to the window. This works in IE 6/7/8, FireFox, Safari but not Chrome.
            // Well in Chrome it works the first time, but subsequent focus attempts fail,. I believe this is a security feature in Chrome to avoid annoying popups.
            windowHandles[windowTarget].focus();
        }
        else
        {
            // Need to do this so that tabbed browsers (pretty much all browsers except IE6) actually open a new window
            // as opposed to a tab. By specifying at least one window property, we're guaranteed to have a new window created instead
            // of a tab.
            windowProperties = windowProperties || 'menubar=yes,location=yes,width=700, height=400, scrollbars=yes, resizable= yes';
            windowTarget = windowTarget || "_blank";

            // Create a new window.
            var windowHandle = windowProperties ? window.open(url, windowTarget, windowProperties) : window.open(url, windowTarget);

            if (null === windowHandle) {
                alert("You have a popup blocker enabled. Please allow popups for " + location.protocol + "//" + location.host);
            }
            else {
                if ("_blank" !== windowTarget) {
                    // Store the window handle for reuse if a handle was specified.
                    windowHandles[windowTarget] = windowHandle;
                    windowHandles[windowTarget].focus();
                }
            }
        }
    }
}
6个回答

我一直在努力解决这个问题。我想要一个对另一个窗口的引用,所以我发出了一个:

otherWinRef = window.open("","OtherWindow");

但是,当我发出此命令时,浏览器会将焦点切换到其他窗口。我认为这可以通过这样做来解决:

otherWinRef = window.open("","OtherWindow");
window.focus();

但 window.focus() 没有效果。我试过:

otherWinRef = window.open("","OtherWindow");
setTimeout(window.focus,0);

但是 window.focus() 调用仍然没有效果。

我通过将以下代码添加到 OtherWindow 的源中来解决该问题。

function Bounce(w) {

        window.blur();
        w.focus();
}

然后我将主窗口中的代码更改为:

otherWinRef = window.open("","OtherWindow");
otherWinRef.Bounce(window);
此解决方案现在似乎不起作用(2021 年 10 月)
2021-04-26 11:53:55

在 Windows 7 版本 14.0.835.202 m 中仍然相同;找到了另一种解决方法,不是更优雅,但至少可以避免丢失页面上的数据:在要聚焦的窗口中显示警报。

在弹出窗口的情况下,这只会在警报关闭之前返回焦点。
2021-05-12 11:53:55

更新:此解决方案似乎不再适用于 Chrome。

令人难以置信的是,解决方案非常简单。至少一个星期以来,我一直在努力解决这个问题。你需要做的就是模糊窗口然后给它焦点。我以前试过这个,但没有用。

windowHandle.blur();
windowHandle.focus();

所以我最终尝试了这个:

windowHandle.blur();
setTimeout(windowHandle.focus, 0);

这似乎有效。

我在这里更新了我的代码:

MyCompany = { UI: {} }; // Put this here if you want to test the code. I create these namespaces elsewhere in code.

MyCompany.UI.Window = new function() {       
    // Private fields
    var that = this;
    var windowHandles = {};
    var isChrome = /chrome/.test(navigator.userAgent.toLowerCase());

    // Public Members
    this.focus = function(windowHandle) {
        if (!windowHandle) {
            throw new Exception("Window handle can not be null.");
        }

        if (isChrome) {
            windowHandle.blur();
            setTimeout(windowHandle.focus, 0);                    
        }
        else {
            windowHandle.focus();
        }    
    }

    this.windowExists = function(windowTarget) {
        return windowTarget && windowHandles[windowTarget] && !windowHandles[windowTarget].closed;
    }

    this.open = function(url, windowTarget, windowProperties) {
        // See if we have a window handle and if it's closed or not.
        if (that.windowExists(windowTarget)) {

            // We still have our window object so let's check if the URLs is the same as the one we're trying to load.
            var currentLocation = windowHandles[windowTarget].location;

            if (
                (
                    /^http(?:s?):/.test(url) && currentLocation.href !== url
                )
                    ||
                (
                    // This check is required because the URL might be the same, but absolute,
                    // e.g. /Default.aspx ... instead of http://localhost/Default.aspx ...
                    !/^http(?:s?):/.test(url) &&
                    (currentLocation.pathname + currentLocation.search + currentLocation.hash) !== url
                )
            ) {
                // Not the same URL, so load the new one.
                windowHandles[windowTarget].location = url;
            }

            // Give focus to the window. This works in IE 6/7/8, FireFox, Safari but not Chrome.
            // Well in Chrome it works the first time, but subsequent focus attempts fail,. I believe this is a security feature in Chrome to avoid annoying popups.
            that.focus(windowHandles[windowTarget]);
        }
        else {
            // Need to do this so that tabbed browsers (pretty much all browsers except IE6) actually open a new window
            // as opposed to a tab. By specifying at least one window property, we're guaranteed to have a new window created instead
            // of a tab.
            //windowProperties = windowProperties || 'menubar=yes,location=yes,width=700, height=400, scrollbars=yes, resizable= yes';
            windowProperties = windowProperties || 'menubar=yes,location=yes,width=' + (screen.availWidth - 15) + ', height=' + (screen.availHeight - 140) + ', scrollbars=yes, resizable= yes';
            windowTarget = windowTarget || "_blank";

            // Create a new window.
            var windowHandle = windowProperties ? window.open(url, windowTarget, windowProperties) : window.open(url, windowTarget);

            if (null === windowHandle || !windowHandle) {
                alert("You have a popup blocker enabled. Please allow popups for " + location.protocol + "//" + location.host);
            }
            else {
                if ("_blank" !== windowTarget) {
                    // Store the window handle for reuse if a handle was specified.
                    windowHandles[windowTarget] = windowHandle;
                    windowHandles[windowTarget].focus();
                }
            }
        }
    }
}
版本 46.0.2490.86(64 位)Mac OSX 10.11.1。简单的模糊和焦点对我有用。
2021-04-28 11:53:55
在 Windows 7 上的 Chrome 51.0.2704.63 上对我不起作用。我试图将子窗口/弹出窗口重新聚焦到 Web 应用程序上。还没有找到任何方法来做到这一点。
2021-05-01 11:53:55
如果有人对 Mac 上的 Chrome 有解决方法,我将不胜感激!
2021-05-06 11:53:55
似乎 chrome 开发人员在阅读了这里的解决方案后一直保持这种状态:)
2021-05-09 11:53:55
上面的解决方案:windowHandle.blur(); setTimeout(windowHandle.focus, 0); 似乎不适用于 Chrome 8.0.552.237。是否有任何其他解决方法可以使用 setTimeout 将焦点放在弹出窗口上?
2021-05-13 11:53:55

来自某人博客的建议是使用这个:

if (navigator.userAgent.indexOf('Chrome/') > 0) {
    if (window.detwin) {
        window.detwin.close();
        window.detwin = null;
    }
}
window.detwin = window.open(URL,  'windowname', '...');
window.detwin.focus();

关注这个错误可能会有用。

@Rich,我也看到了您提到的错误,但感谢您发帖让其他人看到。
2021-04-18 11:53:55
上面的解决方案:windowHandle.blur(); setTimeout(windowHandle.focus, 0); 似乎不适用于 Chrome 8.0.552.237。是否有任何其他解决方法可以使用 setTimeout 将焦点放在弹出窗口上?
2021-04-26 11:53:55
@Rich,我在问题中提到了这一点。虽然这是一个糟糕的解决方案。如果弹出窗口有您想要保存的数据怎么办?杀死窗口并重新打开网址似乎很糟糕。
2021-05-13 11:53:55

您可以focus通过open使用javascript:;asurl参数调用另一个窗口

window.open('http://....', 'myWindow');

// focus that window later on...
window.open('javascript:;', 'myWindow');
问题不在于关注新窗口。问题是您希望在打开新窗口时将焦点保持在旧窗口上(新窗口在后台打开)。
2021-05-10 11:53:55