window.focus() not working in Google Chrome

99,286

Solution 1

I've been struggling with this issue. I wanted a reference to another window, so I was issuing a:

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

However when I issue this command, the browser will switch focus to the OtherWindow. I thought this could be addressed by doing this:

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

but the window.focus() has no effect. I tried:

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

But the window.focus() call still had no effect.

I resolve the issue by adding the following code to the OtherWindow's source.

function Bounce(w) {

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

Then I changed the code in the main window to:

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

Solution 2

Still the same in version 14.0.835.202 m on Windows 7; found another workaround, not more elegant but at least will avoid losing data on the page: show an alert in the window you want to focus.

Solution 3

UPDATE: This solution appears to no longer work in Chrome.

Unbelievably, the solution is quite simple. I've been trying to figure this issue out for at least a week. All you need to do is blur the window then give it focus. I had tried this previously and it didn't work.

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

So I ended up trying this instead:

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

and that seems to work.

I've updated my code here:

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();
                }
            }
        }
    }
}

Solution 4

Here's a workaround I was able to use. It may not work for everybody, but it does what I need it to, and it does handle scenarios where your popup has been updated via Ajax after the initial load (ie - it doesn't go back to the server to reload the page).

function refocusWindow() {
  var newName = window.name + '-2'; // you'll want to customize this for your needs
  var options = ''; // again, customize for your situation
  var w = window.open('', newName, options);
  w.document.write(document.getElementById('everything').innerHTML);
  window.close();
}    

I'm using the new window trick to make it look like I'm just refocusing the page, but I'm actually creating a new window with the exact contents of the old window and then closing the old window.

You'll just need to make sure that you are able to grab everything you need for the new window. I put everything I need in an #everything div; you may need to change this for your needs.

Hope this at least helps some of you.

Note: inline Javascript seems to execute with this approach, linked Javascript may not. Proceed with caution if this will be a problem for you.

Solution 5

A suggestion from someone's blog is to use this:

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

Following this bug might be useful.

Share:
99,286
nickytonline
Author by

nickytonline

web guy / crime fighter

Updated on July 09, 2022

Comments

  • nickytonline
    nickytonline almost 2 years

    Just wondering if Google Chrome is going to support window.focus() at some point. When I mean support, I mean have it work. The call to it doesn't fail, it just doesn't do anything. All other major browsers do not have this problem: FireFox, IE6-IE8 and Safari.

    I have a client-side class for managing browser windows. When I first create a window the window comes into focus, but subsequent attempts to bring focus to the window do not work.

    From what I can tell, this appears to be a security feature to avoid annoying pop-ups and it does not appear to be a WebKit issue as it works in Safari.

    I know one idea someone brought forward was to close the window then reopen it, but this is a horrible solution. Googling shows that I do not appear to be the only person frustrated with this.

    And just to be 100% clear, I mean new windows, not tabs (tabs cannot be focused from what I've read) and all the windows being opened are in the same domain.

    Any ideas, workarounds aside from the bad one I mention above?

    There is a bug logged on the Chromium project about this, check it out here. Thanks for posting that 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();
                    }
                }
            }
        }
    }
    
  • nickytonline
    nickytonline about 14 years
    @Rich, I mention this in my question. It's a bad solution though. What if the popup has data that you want to save? Killing the window and reopening the url just seems bad.
  • nickytonline
    nickytonline about 14 years
    @Rich, I also saw the bug you mentioned, but thanks for posting for others to see.
  • vilner
    vilner over 13 years
    I am having the same problem but this solution did not work for me. I am using Chrome 5.0.375.125 for Mac OS X (Snow Leopard). Can you confirm that it works on both Windows and Mac?
  • nickytonline
    nickytonline over 13 years
    @Nick - I only tested it on Chrome for Windows.
  • vilner
    vilner over 13 years
    if anyone has a work-around for Chrome on Mac I would appreciate it!
  • teo
    teo over 13 years
    The above solution : windowHandle.blur(); setTimeout(windowHandle.focus, 0); does not seem to work on Chrome 8.0.552.237. Are there any other workarounds to give focus to a popup window using setTimeout?
  • teo
    teo over 13 years
    The above solution : windowHandle.blur(); setTimeout(windowHandle.focus, 0); does not seem to work on Chrome 8.0.552.237. Are there any other workarounds to give focus to a popup window using setTimeout?
  • nickytonline
    nickytonline about 13 years
    It appears that my workaround no longer works. I'm in Chrome 10.x
  • Damir Zekić
    Damir Zekić about 12 years
    Interesting approach! I'm curious how does this affect JS in <script> tags embedded on the page. It's worth noting that this works only for popups opened from the same domain, as cross-origin restrictions would apply. And why don't you just get <html> or <body> with getElementsByTagName instead of having #everything?
  • Marco Demaio
    Marco Demaio about 12 years
    Cool, this works on Chrome 5 for Windows (even w/o setTimeout)
  • tobinibot
    tobinibot about 12 years
    It runs my inline <script> tags just fine, I don't have any JS pulled in from other files. The reason I use my #everything div is that I have JS that I don't want to run when I reopen the page. I realize that's probably not very common, but it's what I needed to do.
  • Damir Zekić
    Damir Zekić about 12 years
    The second part answers exactly what I was asking :) When you refocus the window, no scripts get re-executed, while this approach breaks that assumption. It's not bad, just could be surprising to some, and maybe it needs emphasizing.
  • Jalpesh
    Jalpesh over 11 years
    This used to work, but does not anymore in chrome - 21.0.1180.60 m
  • nickytonline
    nickytonline over 10 years
    @user9761888 - This is a poor solution as you lose the entire state of the page. If you don't care about state, then this works, but still dirty.
  • tobinibot
    tobinibot about 10 years
    @MuhammadUmer yep, but in my situation, that doesn't matter
  • Khadim Ali
    Khadim Ali over 8 years
    Seems chrome developers keep this breaking after reading the solutions here :)
  • Peter
    Peter over 8 years
    Version 46.0.2490.86 (64-bit) Mac OSX 10.11.1. Simple blur and focus works for me.
  • piotr_cz
    piotr_cz over 8 years
    Not on 47.0.2526.106 m (64-bit) on W8.1
  • HK1
    HK1 almost 8 years
    Doesn't work for me on Chrome 51.0.2704.63 on Windows 7. I'm trying to bring child/popup windows back into focus on a web application. Haven't found any way to do it yet.
  • Blag
    Blag over 7 years
    Please don't forget to explain / comment your code, and provide relevant documentation [from review]
  • Robert Moore
    Robert Moore almost 7 years
    In the case of pop-unders, this will only return focus until the alert is closed.
  • awe
    awe almost 4 years
    The issue is not to focus the new window. The issue is that you want to keep focus to the old window when opening the new (new opens in background).
  • Ruben Estrada
    Ruben Estrada over 2 years
    This solution doesn't seem to be working now (October 2021)
  • Mohammed Khurram
    Mohammed Khurram almost 2 years
    This solution would work if not violating CORS.