添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I can't seem to get this to work.

In response to a click, window A opens window B (which then has focus). Then, in response to a click on B, the window calls window.opener.focus() , but the focus does not go back to A.

I have found a strange, strange workaround for Chrome (29, possibly others). If I run:

window.opener.name = 'somename';
window.open(window.opener.location.href, window.opener.name);
window.opener.focus();

it does work (and doesn't reload window A). But this doesn't work for Firefox, and it is probably a fluke anyway.

It seems very clear to me what opener and focus are supposed to do, but window.opener.focus() doesn't work. What am I missing?

Makes a request to bring the window to the front. It may fail due to user settings and the window isn't guaranteed to be frontmost before this method returns.

Emphasis mine. Calling focus() is just a request and the browser is free to ignore you and you should generally expect to be ignored. Consider what sorts of nefarious things you could get up to by switching focus to a tiny window while someone is typing if you need some reasons why a browser would ignore your request.

If you need focus() to work for your application to work then you need to redesign your application so that it doesn't need to call focus().

(1) "It may fail due to user settings." What user settings are causing this? (2) "The window isn't guaranteed to be the frontmost before this method returns." I don't care if it is in front at the end of the call; I just want it in front eventually. – Paul Draper Aug 29, 2013 at 2:42 @PaulDraper If this is for a public website, then you just can't (reliably) have want you're asking for. – David-SkyMesh Aug 29, 2013 at 2:43

I can see why a browser/OS will not allow a child windows to take over the focus (abuse of power). Here is a workaround:

  • In the parent window, declare a function in "window.external" that will trigger Javascript "alert()" or "confirm()".
  • Invoke that function from the child window.
  • The browser might ignore a request from a child window that wants to control the focus (e.g. window.opener.focus()), but the browser should honor a request from a parent window that triggers an alert() or a confirm() action, which requires to focus on the parent window.
  • JS Parent:

        var child = window.open('child.html', 'child');
        window.external.comeback = function() {
            var back = confirm('Are you sure you want to comback?');
            if(back) {
                child.close();
            } else {
                child.focus();
    

    JS Child:

        // assuming you have jQuery
        $('.btn').click() {
            window.opener.external.comeback();  
    

    --I am using this code in a real world application to handle a checkout request that runs in child window, and I need to gracefully return to the parent window.

    This no longer works in Chrome. The popup is done in the other tab, but doesn't show up until you happen to look at that tab. – Glen Little Oct 15, 2018 at 17:25 This gives a error "Blocked Blocked a frame with origin "localhost" from accessing a cross-origin frame. at <anonymous>:2:15" – rottitime Aug 17, 2021 at 16:18

    Web-facing or private intranet?

    Window management is up to the Browser and the OS. HTML & ECMAscript have nothing to say about it.

    If this is for a public-facing website, then just don't bother -- as they say, "Don't break the web."

    But I really wanna!

    If this is for some tightly managed (say Intranet) application of some kind then you'll need to resort to writing Addons/Extensions. It's certaintly easier if you can restrict yourself to a single browser & platform.

    EDIT: Example for Firefox on Win32...

    This solution works as a custom addon for Firefox which uses jsctypes internally to load a Win32 DLL. The window_focus() JavaScript function is exposed which does what you want.

    There are 3 parts to this solution:

    1. The privileged JavaScript code to load/bind the Win32 APIs
    2. The CPP header file for our external DLL
    3. The CPP source file for our external DLL
    4. I built a simple GUI DLL project in MSVC++ with the later two files & compiled wmctrl.dll, depending on msvcr100.dll, and used Dependency Walker to find the "plain C" symbols exported by the DLL for use by js-ctypes. E.g: ?wmctrl_find_window@@YAKPAD@Z is the "plain C" symbol for the C++ api function called wmctrl_find_window.

      As a caveat, this code relies on temporarily being able to change the title of the window that needs to be focused so that Win32 APIs can examine all windows on your desktop to find the correct Firefox window.

      You need to have access to privileged Mozilla platform APIs, i.e: JavaScript inside a Firefox Addon.

      In your privileged JavaScript code:

      // get API constants (might already be available)
      const {Cc,Ci,Cu} = require("chrome");
      // import js-ctypes
      var file=null, lib=null, ctypes = {};
      Cu.import("resource://gre/modules/ctypes.jsm", ctypes);
      var ctypes = ctypes.ctypes;
      // build platform specific library path
      var filename = ctypes.libraryName("wmctrl"); // automatically adds '.dll'
      var comp = "@mozilla.org/file/directory_service;1";
      var file = Cc[comp].getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile);
      file.append("browser_code"); // or whereever you put your DLL
      file.append(filename);
      // get the JavaScript library interface (load the library)
      var lib = ctypes.open(file.path);
      // wmctrl_find_window: returing unsigned 32bit (long) "window handle"
      // takes string "window title".
      var find_window = lib.declare(
          "?wmctrl_find_window@@YAKPAD@Z",     /* plain "C" DLL symbol  */
          ctypes.stdcall_abi, ctypes.uint32_t, /* return type: uint32   */
          ctypes.char.ptr);                    /* parameter: string     */
      // wmctrl_window_focus: takes unsigned 32bit (long) "window handle".
      var window_focus = lib.declare(
          "?wmctrl_window_focus@@YAXK@Z",      /* plain "C" DLL symbol  */
          ctypes.stdcall_abi, ctypes.void_t,   /* return type: void     */
          ctypes.uint32_t);                    /* parameter: uint32     */
      

      wmctrldll.h

      #ifdef WMCTRLDLL_EXPORTS
      #define WMCTRLDLL_API __declspec(dllexport)
      #else
      #define WMCTRLDLL_API __declspec(dllimport)
      #endif
      WMCTRLDLL_API void wmctrl_window_focus (unsigned long wid);
      WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title);
      

      wmctrldll.cpp

      typedef struct {
        HWND hWnd;
        char title[255];
      } myWinSpec;
      BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
        char String[255];
        myWinSpec* to_find = (myWinSpec*) lParam;
        // not a window
        if (!hWnd) return TRUE;                                   
        // not visible
        if (!IsWindowVisible(hWnd)) return TRUE;
        // no window title                  
        if (!GetWindowTextA(hWnd, (LPSTR)String, 255)) return TRUE;
        // no title match
        if (strcmp(String, to_find->title) != 0) return TRUE;     
        to_find->hWnd = hWnd;
        return FALSE;
      WMCTRLDLL_API void wmctrl_window_focus(unsigned long wid) {
        SetForegroundWindow((HWND) wid);
      WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title) {
        myWinSpec to_find;
        sprintf_s(to_find.title, sizeof(to_find.title), "%s", find_title);
        to_find.hWnd = 0;
        EnumWindows(EnumWindowsProc, (LPARAM)&to_find);
        return (unsigned long) to_find.hWnd;
                      "Window management is up to the Browser and the OS." Then what should we make of window.open(), window.blur(), and window.focus()?
      – Paul Draper
                      Aug 29, 2013 at 2:44
                      window.open() is to open a new child window of your current browser window. Management of the window is still up to the Browser/OS. The .blur() and .focus() methods are really there for completeness of the interface when compared to other DOM objects -- they can't and won't override the user-settings nor operating system.
      – David-SkyMesh
                      Aug 29, 2013 at 2:46
                      @PaulDraper: JavaScript is fairly old and we have learned a few lessons about what is and is not a good idea. We're stuck pretending to support a lot of the bad ideas.
      – mu is too short
                      Aug 29, 2013 at 3:24
      

      I found a reasonable workaround for this using web Notifications.

      As mentioned in some of the other answers here there are some constraints with browsers and the OS where window.opener.focus() may not work.

      I was able to get this to work using postMessage and Notifications.

      To try this out: From the parent (opener) tab add a 'message' event listener that creates a notification with a click listener:

       window.addEventListener("message", (event) => {
        if (!("Notification" in window)) {
          alert("This browser does not support desktop notification");
        // Let's check whether notification permissions have already been granted
        else if (Notification.permission === "granted") {
          // If it's okay let's create a notification
          var notification = new Notification("The opener needs your attention");
          // Add click listener that will perform a window focus
          notification.onclick = function (x) {
            window.focus();
            this.close();
        // Otherwise, we need to ask the user for permission
        else if (Notification.permission !== "denied") {
          Notification.requestPermission().then(function (permission) {
            // If the user accepts, let's create a notification
            if (permission === "granted") {
              var notification = new Notification("The opener needs your attention");
              // Add click listener that will perform a window focus
              notification.onclick = function (x) {
                window.focus();
                this.close();
      

      Then from the child tab you need to use postMessage when focus back to parent tab is needed:

      // Called from child tab
      window.opener.postMessage(
          message: "focus",
        "*" // cross-origin
      

      Once you call postMessage you should see a OS Web notification. If a user clicks this they should be redirected to the parent (opener) tab.

          function here() {
              alert('Welcome Back')  // seems needed to wake up document
              window.focus()
      

      In opened window invoke script function:

          function HomeTab()  {
              O = window.opener;
              if (O)
                  if (O.closed)   alert('Home page has been closed')
                  else    O.here()
              else alert('This tab has no home page')
      

      Works widely differently in different browsers Some will have the parent tab blink Some mark the parent tab, and you have to notice it Some you have to click on home tab the first time and you can then give it permission to go directly to home tab without a confirm box.

      This gives a error "Blocked Blocked a frame with origin "localhost" from accessing a cross-origin frame. at <anonymous>:2:15" – rottitime Aug 17, 2021 at 16:16

      Thanks for contributing an answer to Stack Overflow!

      • Please be sure to answer the question. Provide details and share your research!

      But avoid

      • Asking for help, clarification, or responding to other answers.
      • Making statements based on opinion; back them up with references or personal experience.

      To learn more, see our tips on writing great answers.