2008-10-01 8 views
20

Je voudrais vérifier si le navigateur actuel supporte l'événement onbeforeunload. La façon javascript courante de faire cela ne semble pas fonctionner:onbeforeunload support detection

if (window.onbeforeunload) { 
    alert('yes'); 
} 
else { 
    alert('no'); 
} 

En fait, il ne vérifie si certains gestionnaire a été attaché à l'événement. Y at-il un moyen de détecter si onbeforeunload est pris en charge sans détecter le nom de navigateur particulier?

Répondre

27

J'ai écrit plus ou moins sur reliable inference for detecting event support dans les navigateurs modernes il y a quelque temps. Vous pouvez voir sur une page de démonstration que "beforeunload" est supporté dans au moins Safari 4+, FF3.x + et IE.

Modifier: Cette technique est maintenant utilisée dans jQuery, Prototype.js, Modernizr, et probablement d'autres scripts et bibliothèques.

+1

fonctionne parfaitement merci pour le partage – jansokoly

+1

Le site qui est lié à ci-dessus vers le bas? Ne fonctionne pas pour moi mais j'ai trouvé une [version en cache] (http://webcache.googleusercontent.com/search?q=cache:http://perfectionkills.com/detecting-event-support-without-browser-sniffing /). – regularmike

+1

Attention: J'ai écrit un commentaire sur la page [@ kangax] (http://perfectionkills.com/detecting-event-support-without-browser-sniffing/#comment-468226) spécifiquement sur 'onbeforeunload' étant détecté comme supporté sur Mobile Safari même s'il [ne fonctionne pas réellement] (http://stackoverflow.com/questions/3239834/window-onbeforeun-not-working-on-the-ipad). –

-4

Il serait sans doute préférable de trouver tout à la main les navigateurs prennent en charge et ensuite votre condition plus comme:

if($.browser.msie) { 
    alert('no'); 
} 

... etc.

La syntaxe $.browser.msie est la syntaxe jQuery, la plupart des frameworks ont des fonctions intégrées similaires puisqu'ils les utilisent beaucoup en interne. Si vous n'utilisez pas de framework, je vous suggère de regarder l'implémentation de ces fonctions par jQuery.

0

approche différente, obtenir le typeof

if(typeof window.onbeforeunload == 'function') 

{ 
alert("hello functionality!"); 
} 
+0

ne semble pas fonctionner non plus – jansokoly

+1

sur quel navigateur penses-tu? – curtisk

+0

tous, IE, Opera, Safari, Firefox votre code ne fonctionne pas dans n'importe quel navigateur si (typeof window.onbeforeunload! = 'Undefined') est proche, mais échoue en FF – jansokoly

2
alert('onbeforeunload' in window); 

Alertes 'true' si onbeforeunload est une propriété de window (même si elle est nulle).

Cela devrait faire la même chose:

var supportsOnbeforeunload = false; 
for (var prop in window) { 
    if (prop === 'onbeforeunload') { 
    supportsOnbeforeunload = true; 
    break; 
    } 
} 
alert(supportsOnbeforeunload); 

Enfin:

alert(typeof window.onbeforeunload != 'undefined'); 

Encore une fois, typeof window.onbeforeunload semble être 'objet', même si elle a actuellement la valeur null, donc cela fonctionne.

+0

presque fonctionne très bien dans IE, Opéra et Safari, mais FF me donne faux, ce qui ne semble pas correct – jansokoly

+0

Désolé, je pensais que cela fonctionnait de manière fiable car je ne savais pas que Firefox supportait onbeforeunload. –

+0

Firefox ne supporte pas ce genre d'inférence, mais permet de détecter "beforeunload" en réglant l'attribut correspondant sur un élément. var el = document.createElement ('div'); el.setAttribute ('onbeforeunload', ''); typeof el.onbeforeunload; // "function" – daniellmb

2

cruster,

Le "beforeunload" n'est pas définie dans la spécification DOM-Events, ceci est une caractéristique spécifique à IE. Je pense qu'il a été créé afin de permettre à l'exécution d'être déclenchée avant l'événement "unload" standard. Dans d'autres navigateurs IE, vous pouvez utiliser l'écouteur d'événement "unload" en phase de capture, ce qui permet d'exécuter du code avant, par exemple, un événement onunload de corps en ligne.

En outre, DOM ne propose aucune interface pour tester son soutien à un événement spécifique, vous ne pouvez tester pour le soutien d'un groupe d'événements (MouseEvents, MutationEvents etc.)

En attendant, vous pouvez également consulter à la spécification DOM-Events http://www.w3.org/TR/DOM-Level-3-Events/events.html (malheureusement pas pris en charge dans IE)

espère que cette information aide certains

+1

Merci mon pote, mais ce n'est que de la théorie - voir les autres réponses à ces questions et vous trouverez des solutions presque parfaites. Donc, je m'en fiche vraiment si DOM offre une interface ou non. En réalité, il existe des moyens fiables de vérifier, c'est important. Oh, d'accord, seulement Opera n'a pas le soutien. – jansokoly

0

onbeforeunload est également pris en charge par FF, afin de tester pour le navigateur ne sera pas utile.

6

Je me rends compte que je suis un peu en retard sur celui-ci, mais je fais face à cela maintenant, et je pensais que quelque chose de plus comme ce qui suit serait plus facile et plus fiable. Ceci est spécifique à jQuery, mais il devrait fonctionner avec n'importe quel système qui vous permet de lier et de dissocier des événements.

$(window).bind('unload', function(){ 
    alert('unload event'); 
}); 

window.onbeforeunload = function(){ 
    $(window).unbind('unload'); 
    return 'beforeunload event'; 
} 

Cela devrait délier l'événement unload si l'événement se déclenche beforeunload. Sinon, il va simplement déclencher le déchargement.

7

Malheureusement, kangax's answer ne fonctionne pas pour Safari on iOS. Dans mes tests beforeunload a été pris en charge dans tous les navigateurs j'ai essayé exactement sauf Safari sur iOS :-(

Au lieu de cela, je suggère une approche différente.

L'idée est simple sur la première visite de la page, nous ne sommes pas réellement savoir encore si beforeunload est pris en charge. Mais cette première page, nous mettons en place à la fois un unload et un gestionnaire beforeunload. Si le feu gestionnaire beforeunload, nous avons mis un drapeau disant que beforeunload est pris en charge (en fait beforeunloadSupported = "yes"). Lorsque les unload incendies de gestionnaire, si le drapeau n'a pas été défini, nous avons mis le drapeau que beforeunload est pas pris en charge.

Dans ce qui suit, nous allons utiliser localStorage (pris en charge dans tous les navigateurs que je garde au sujet - voir http://caniuse.com/namevalue-storage) pour obtenir/définir le drapeau. Nous aurions tout aussi bien pu utiliser un cookie, mais j'ai choisi localStorage parce que n'a aucune raison d'envoyer cette information au serveur web à chaque requête. Nous juste besoin d'un drapeau qui survit à recharges de page. Une fois que nous l'avons détecté une fois, il restera détecté pour toujours.

Avec ceci, vous pouvez maintenant appeler isBeforeunloadSupported() et il vous le dira.

(function($) { 
    var field = 'beforeunloadSupported'; 
    if (window.localStorage && 
     window.localStorage.getItem && 
     window.localStorage.setItem && 
     ! window.localStorage.getItem(field)) { 
     $(window).on('beforeunload', function() { 
      window.localStorage.setItem(field, 'yes'); 
     }); 
     $(window).on('unload', function() { 
      // If unload fires, and beforeunload hasn't set the field, 
      // then beforeunload didn't fire and is therefore not 
      // supported (cough * iPad * cough) 
      if (! window.localStorage.getItem(field)) { 
       window.localStorage.setItem(field, 'no'); 
      } 
     }); 
    } 
    window.isBeforeunloadSupported = function() { 
     if (window.localStorage && 
      window.localStorage.getItem && 
      window.localStorage.getItem(field) && 
      window.localStorage.getItem(field) == "yes") { 
      return true; 
     } else { 
      return false; 
     } 
    } 
})(jQuery); 

Voici un exemple complet de avec l'exemple d'utilisation.

Notez qu'il n'a été détecté que sur le second ou les chargements de pages suivants sur votre site. S'il est important pour vous de le faire fonctionner sur la toute première page, vous pouvez charger un iframe sur cette page avec un attribut src pointant vers une page du même domaine avec la détection ici, assurez-vous qu'il a été chargé puis supprimé il. Cela devrait assurer que la détection a été faite, donc isBeforeunloadSupported() fonctionne même sur la première page. Mais je n'avais pas besoin de ça alors je ne l'ai pas mis dans ma démo.

-1

Je vois que c'est un fil très vieux, mais la réponse acceptée détecte de manière incorrecte support pour Safari sur iOS, ce qui m'a amené à étudier d'autres stratégies:

if ('onbeforeunload' in window && typeof window['onbeforeunload'] === 'function') { 
    // onbeforeunload is supported 
} else { 
    // maybe bind to unload as a last resort 
} 

La deuxième partie de la si-Check est nécessaire pour Safari sur iOS, dont la propriété est définie sur null.

Testé dans Chrome 37, IE11, Firefox 32 et Safari pour iOS 7.1

+0

'onbeforeunload' est toujours défini sur null par défaut. Si vous définissez une fonction 'onbeforeunload', ce sera toujours une fonction. Cela ne veut pas dire que ça va être déclenché. Je ne fais pas ce que tu as testé, mais ça ne marchera pas. La seule façon ici est la détection d'appareils iOS ou la méthode de Peter V. Mørch. – hexalys