web-dev-qa-db-fra.com

window.focus () ne fonctionne pas dans Google Chrome

Je me demandais simplement si Google Chrome prendrait en charge window.focus() à un moment donné. Quand je parle de soutien, je veux dire que ça marche. L'appel à cela n'échoue pas, il ne fait rien. Tous les autres navigateurs principaux n'ont pas ce problème: FireFox, IE6-IE8 et Safari.

J'ai une classe côté client pour la gestion des fenêtres de navigateur. Lorsque je crée une fenêtre pour la première fois, la fenêtre est mise au point, mais les tentatives suivantes pour la mettre en évidence ne fonctionnent pas.

D'après ce que je peux dire, cela semble être une fonction de sécurité pour éviter les fenêtres publicitaires intempestives gênantes et cela ne semble pas être un problème de WebKit, car cela fonctionne dans Safari.

Je sais que l’idée proposée par quelqu'un était de fermer la fenêtre puis de la rouvrir, mais c’est une solution horrible. Googler montre que je ne semble pas être la seule personne frustrée par cela.

Et juste pour être clair à 100%, je veux dire les nouvelles fenêtres, pas les onglets (les onglets ne peuvent pas être focalisés à partir de ce que j'ai lu) et toutes les fenêtres ouvertes sont dans le même domaine.

Des idées, des solutions en dehors de la mauvaise que je mentionne ci-dessus?

Il y a un bug sur ce projet dans le projet Chromium, allez voir ici . Merci de poster cela 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();
                }
            }
        }
    }
}
39
nickytonline

J'ai eu du mal avec ce problème. Je voulais une référence à une autre fenêtre, alors je publiais un:

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

Cependant, lorsque j'émets cette commande, le navigateur bascule vers l'autre fenêtre. Je pensais que cela pourrait être résolu en faisant ceci:

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

mais le window.focus () n'a aucun effet. J'ai essayé:

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

Mais l'appel de window.focus () n'a toujours aucun effet. 

Je résous le problème en ajoutant le code suivant à la source de OtherWindow.

function Bounce(w) {

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

Ensuite, j'ai changé le code dans la fenêtre principale pour:

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

Toujours la même chose dans la version 14.0.835.202 m sur Windows 7; trouvé une autre solution de contournement, pas plus élégante mais qui évitera au moins de perdre des données sur la page: affichez une alerte dans la fenêtre que vous souhaitez mettre au point.

8
Sti

MISE À JOUR: Cette solution semble ne plus fonctionner sous Chrome.

Incroyablement, la solution est assez simple. J'essaie de résoudre ce problème depuis au moins une semaine. Tout ce que vous avez à faire est de flouter la fenêtre puis de la mettre au point. J'avais déjà essayé cela auparavant et cela ne fonctionnait pas.

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

Alors j'ai fini par essayer ceci à la place:

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

et cela semble fonctionner.

J'ai mis à jour mon code ici:

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

vous pouvez focus une autre fenêtre en appelant open avec javascript:; en tant que paramètre url:

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

// focus that window later on...
window.open('javascript:;', 'myWindow');
3
pwolaq

Une suggestion de le blog de quelqu'un est d'utiliser ceci:

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

Suivre ce bug pourrait être utile.

3
Rich Bradshaw

Voici une solution de contournement que j'ai pu utiliser. Cela peut ne pas fonctionner pour tout le monde, mais il fait ce dont j'ai besoin, et gère les scénarios dans lesquels votre popup a été mis à jour via Ajax après le chargement initial (c'est-à-dire qu'il ne revient pas au serveur pour recharger la 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();
}    

J'utilise la nouvelle astuce de fenêtre pour donner l'impression que je suis juste en train de recentrer la page, mais je crée en fait une nouvelle fenêtre avec le contenu exact de l'ancienne fenêtre, puis en fermant l'ancienne.

Vous devrez simplement vous assurer que vous êtes en mesure de récupérer tout ce dont vous avez besoin pour la nouvelle fenêtre. Je mets tout ce dont j'ai besoin dans un #everything div; vous devrez peut-être changer cela pour vos besoins.

J'espère que cela aide au moins certains d'entre vous.

Note : inline Javascript semble fonctionner avec cette approche, le Javascript lié ne peut pas. Procédez avec prudence si cela vous pose problème.

2
tobinibot

window.focus() pour les fenêtres enfants fonctionne correctement pour Chrome v52 sous Windows, mais UNIQUEMENT dans un événement initié par l'utilisateur, par exemple un clic de rappel. (Il s'agit de la même restriction que la fenêtre contextuelle bloquée s'applique aux appels window.open().)

2
Rich

La seule solution qui fonctionne actuellement dans Chrome est ce code dans une nouvelle fenêtre:

$(".closeBtn").click( function(e) 
{
    window.open("",window.opener.name);
    window.close();
});

Malheureusement, la solution ne fonctionne que sous deux conditions:

  • window.opener doit avoir son nom défini lors du chargement du document (window.name="WhateverName";)
  • window.open() est appelée lorsque l'utilisateur clique
1
Matej Balantič

Ce n’est peut-être pas ce que tout le monde veut, mais (en chrome), j’ai remarqué qu’une alerte déclenchée à partir de la page contextuelle est maintenue au centre de la fenêtre. Alors je fais ça maintenant ...

Sur la page qui apparaît, une fonction est chargée dans l'en-tête:

<script type="text/javascript">
    function confirmBlur() {
        if (confirm("Do you want to close this window?")) {
            window.close();
        }
    }
</script>`

Et puis sur la page pop up:

<body onblur="ConfirmBlur()">

Il s’agit donc d’une variante de la fermeture de la fenêtre contextuelle lorsque la mise au point est perdue. Mais dans mon cas, le popup est une fenêtre d'édition pour les données. Une fenêtre, on ne veut pas fermer sans rien demander. Alors maintenant, l'utilisateur est averti que le focus est sur le point de tomber et obtient le choix s'il veut fermer la fenêtre ou non. Encore une fois, loin d'être parfait, mais cela a fonctionné pour moi.

(sois gentil)

0
vonDutch

Aucune des solutions ici ne fonctionnait pour moi. Donc, je suis venu avec ceci:

$('<form target="_blank" action="'+URL+'" method="post"></form>')
    .appendTo('body').submit();

Cela crée un formulaire vierge soumis par la poste à l'URL cible. En appliquant target="_blank", nous imitons l’appel de window.open () avec l’effet secondaire de maintenir le focus sur la nouvelle fenêtre.

Edit: Vanilla JS version qui supprime également l'élément de formulaire par la suite:

var f = document.createElement("form");
f.setAttribute('method', 'post');
f.setAttribute('action', URL);
f.setAttribute('target', '_blank');
document.getElementsByTagName('body')[0].appendChild(f);
f.submit();
f.parentNode.removeChild(f);
0
javon27

Je viens de découvrir une solution assez simple.

Si vous rouvrez une fenêtre située à l'arrière-plan et ciblant la même fenêtre ("_self"), Chrome la met automatiquement en évidence.

Pour reprendre le focus d'une fenêtre, utilisez le code suivant:

path = windowHandle.document.URL;
windowHandle.open(path,"_self");
0
Raposo

Cela fonctionne très bien pour moi . Suppression du lancement de la fenêtre vierge du bloc catch, au lieu de lancer directement l'URL, ce qui évite la confusion de l'utilisateur lorsqu'il dit fenêtre vierge.

windowHandle = window.open('', 'PrintInvoice', urlOptions);
try {
    windowHandle.document.location.href = url;
} catch (exc) {
    windowHandle.close();
    windowHandle = window.open(url, 'PrintInvoice', urlOptions);
}
windowHandle.focus();
0
Praveena M

Je me suis battu dans Chrome. Je voulais qu'une fenêtre contextuelle s'affiche lorsque l'utilisateur clique sur un lien de l'écran parent. Fonctionne la première fois que la fenêtre contextuelle est affichée, mais une fois que celle-ci perd son focus, javascript ne peut plus la ramener au premier plan; vous devez cliquer manuellement sur la fenêtre. Voici ce qui a fonctionné pour moi. Ce script est la fenêtre parente (celle avec les liens). Comme vous pouvez le voir, je le mets à la fin de la section HEAD:

<script type="text/javascript">
  var infoWindow;

  function openLink(url)   {
    infoWindow = window.open("", "infoWindow", "width=880, height=500, top=20, left=20, scrollbars=yes, toolbar=yes, resizable=yes");
    infoWindow.location.href=url;
    infoWindow.focus();
  }

  function closeWindow()   {
    if (infoWindow)   {
      infoWindow.close();
    }
  }
</script>
</head>
<body bgcolor="black" onFocus="closeWindow()" onLoad="closeWindow()">

Tous les liens sont <A href="Javascript: openLink('url')">. Si l'utilisateur ne ferme pas manuellement la fenêtre contextuelle, celle-ci le sera lorsque la fenêtre parent sera réactivée. Donc, le popup est détruit et recréé à chaque fois. Cela semble un peu compliqué, mais cela fonctionne pour moi.

0
Uncle Mike