Comment utiliser Modernizr pour détecter IE?

84

Je voulais utiliser la bibliothèque Modernizr JS pour détecter certaines propriétés du navigateur afin de déterminer le contenu à afficher ou non.

J'ai une application appelée Pano2VR qui produit à la fois HTML5 et SWF. J'ai besoin du HTML5 pour les utilisateurs d'appareils iOS.

Cependant, IE ne rend pas du tout cette sortie "HTML5". Il semble que leur sortie utilise des transformations 3D CSS3 et WebGL, une ou plusieurs apparemment non prises en charge dans IE9.

Donc, pour ces utilisateurs, j'ai besoin d'afficher la version Flash. J'avais l'intention d'utiliser un IFRAME et de transmettre le SRC via un script Modernizr ou un document.Write le code IFRAME correct en fonction du navigateur.

Tout cela conduit à comment utiliser Modernizr pour détecter simplement IE ou non IE? Ou détecter les transformations CSS 3D?

Ou est-ce qu'il y a un autre moyen de le faire?

Steve
la source

Réponses:

1

Je suis d'accord que nous devrions tester les fonctionnalités, mais il est difficile de trouver une réponse simple à "quelles fonctionnalités sont prises en charge par les" navigateurs modernes "mais pas par les" anciens navigateurs "?"

J'ai donc lancé un tas de navigateurs et inspecté directement Modernizer. J'ai ajouté quelques fonctionnalités dont j'ai vraiment besoin, puis j'ai ajouté "inputtypes.color" car cela semble couvrir tous les principaux navigateurs qui me tiennent à cœur: Chrome, Firefox, Opera, Edge ... et PAS IE11. Maintenant, je peux doucement suggérer que l'utilisateur serait mieux avec Chrome / Opera / Firefox / Edge.

C'est ce que j'utilise - vous pouvez modifier la liste des choses à tester pour votre cas particulier. Renvoie false si l'une des fonctionnalités est manquante.

/**
 * Check browser capabilities.
 */
public CheckBrowser(): boolean
{
    let tests = ["csstransforms3d", "canvas", "flexbox", "webgl", "inputtypes.color"];

    // Lets see what each browser can do and compare...
    //console.log("Modernizr", Modernizr);

    for (let i = 0; i < tests.length; i++)
    {
        // if you don't test for nested properties then you can just use
        // "if (!Modernizr[tests[i]])" instead
        if (!ObjectUtils.GetProperty(Modernizr, tests[i]))
        {
            console.error("Browser Capability missing: " + tests[i]);
            return false;
        }
    }

    return true;
}

Et voici cette méthode GetProperty qui est nécessaire pour "inputtypes.color".

/**
 * Get a property value from the target object specified by name.
 * 
 * The property name may be a nested property, e.g. "Contact.Address.Code".
 * 
 * Returns undefined if a property is undefined (an existing property could be null).
 * If the property exists and has the value undefined then good luck with that.
 */
public static GetProperty(target: any, propertyName: string): any
{
    if (!(target && propertyName))
    {
        return undefined;
    }

    var o = target;

    propertyName = propertyName.replace(/\[(\w+)\]/g, ".$1");
    propertyName = propertyName.replace(/^\./, "");

    var a = propertyName.split(".");

    while (a.length)
    {
        var n = a.shift();

        if (n in o)
        {
            o = o[n];

            if (o == null)
            {
                return undefined;
            }
        }
        else
        {
            return undefined;
        }
    }

    return o;
}
Etherman
la source
195

Modernizr ne détecte pas les navigateurs en tant que tels, il détecte les fonctionnalités et capacités présentes et c'est tout ce qu'il essaie de faire.

Vous pouvez essayer de vous connecter à un script de détection simple comme celui-ci, puis de l'utiliser pour faire votre choix. J'ai également inclus la détection de version au cas où cela serait nécessaire. Si vous ne voulez vérifier que n'importe quelle version d'IE, vous pouvez simplement rechercher le navigator.userAgent ayant la valeur "MSIE".

var BrowserDetect = {
        init: function () {
            this.browser = this.searchString(this.dataBrowser) || "Other";
            this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown";
        },
        searchString: function (data) {
            for (var i = 0; i < data.length; i++) {
                var dataString = data[i].string;
                this.versionSearchString = data[i].subString;

                if (dataString.indexOf(data[i].subString) !== -1) {
                    return data[i].identity;
                }
            }
        },
        searchVersion: function (dataString) {
            var index = dataString.indexOf(this.versionSearchString);
            if (index === -1) {
                return;
            }

            var rv = dataString.indexOf("rv:");
            if (this.versionSearchString === "Trident" && rv !== -1) {
                return parseFloat(dataString.substring(rv + 3));
            } else {
                return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
            }
        },

        dataBrowser: [
            {string: navigator.userAgent, subString: "Edge", identity: "MS Edge"},
            {string: navigator.userAgent, subString: "MSIE", identity: "Explorer"},
            {string: navigator.userAgent, subString: "Trident", identity: "Explorer"},
            {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},
            {string: navigator.userAgent, subString: "Opera", identity: "Opera"},  
            {string: navigator.userAgent, subString: "OPR", identity: "Opera"},  

            {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"}, 
            {string: navigator.userAgent, subString: "Safari", identity: "Safari"}       
        ]
    };
    
    BrowserDetect.init();
    document.write("You are using <b>" + BrowserDetect.browser + "</b> with version <b>" + BrowserDetect.version + "</b>");

Vous pouvez alors simplement vérifier:

BrowserDetect.browser == 'Explorer';
BrowserDetect.version <= 9;
Code unique
la source
2
Merci. J'ai fini par découvrir que le problème était que leur fichier avait besoin du support Webgl. Donc, je pourrais utiliser Modernizer pour tester cela et faire un document.write d'un bloc de code de l'autre. Mais c'est une excellente solution pour la détection du navigateur. Merci encore.
Steve
2
Une chose à retenir: la chaîne UA est entièrement configurable par l'utilisateur. Vérifier la chaîne UA n'est donc PAS une manière cohérente de vérifier le navigateur. developer.mozilla.org/en-US/docs/DOM/window.navigator.userAgent Dans la section "Notes":Browser identification based on detecting the user agent string is unreliable and is not recommended, as the user agent string is user configurable.
Andrew Senner
51
Oui, mais quel pourcentage d'utilisateurs naviguent sur le Web avec une chaîne UA modifiée / usurpée / incorrecte? Combien de temps d'ingénierie souhaitez-vous consacrer à ce qu'une infime minorité bénéficie d'une expérience optimale sur votre site? Le reniflement du navigateur via une chaîne UA est une approche pratique et sensée.
Jed Richards
17
@Wintamute, je ne peux pas être plus d'accord. Lassez-vous de la sorte de conférence «la détection des fonctionnalités est diabolique». Nous faisons de l'ingénierie, pas de l'art
Philip007
9
L'hypothèse générale est que si quelqu'un modifie sa chaîne UA, il sait ce qu'il fait et peut gérer les conséquences. En fait, c'est exactement ce pour quoi la chaîne UA existe: déclarer la version du navigateur au serveur. Si le client veut mentir à ce sujet, eh bien, c'est juste la vie! Bien sûr, il y a une petite possibilité que la chaîne soit modifiée sans le consentement de l'utilisateur, mais en pratique, ce n'est pas un réel problème - et sommes-nous censés nourrir l'utilisateur et lui frotter le dos aussi?
Rolf
20

Vous pouvez utiliser Modernizr pour détecter simplement IE ou non IE, en vérifiant SVG SMIL prise en charge de l'animation .

Si vous avez inclus la détection de fonctionnalités SMIL dans votre configuration Modernizr, vous pouvez utiliser une approche CSS simple et cibler la classe .no-smil que Modernizr applique à l' élément html :

html.no-smil {
  /* IE/Edge specific styles go here - hide HTML5 content and show Flash content */
}

Alternativement, vous pouvez utiliser Modernizr avec une approche JavaScript simple, comme ceci:

if ( Modernizr.smil ) {
  /* set HTML5 content */
} else {
  /* set IE/Edge/Flash content */
}

Gardez à l'esprit qu'IE / Edge pourrait un jour prendre en charge SMIL , mais il n'est actuellement pas prévu de le faire.

Pour référence, voici un lien vers le tableau de compatibilité SMIL sur caniuse.com .

jacefarm
la source
Meilleure réponse imo. Si simple
Batman
2
Bien que cela fonctionne, cela fonctionne pour le moment. L'intérêt de la détection des fonctionnalités et de Modernizr est que vous n'avez pas à vous soucier de ce qui se passera demain. Si Edge est mis à jour demain avec le support smil, votre code ne fonctionne plus et vous ne le savez peut-être même pas.
Jason
1
Cela avait l'air si simple, mais apparemment Edge prend désormais en charge SMIL .
Jeremy Carlson
12

Détection des transformations CSS 3D

Modernizr peut détecter les transformations CSS 3D , oui. La véracité deModernizr.csstransforms3d vous dira si le navigateur les prend en charge.

Le lien ci-dessus vous permet de sélectionner les tests à inclure dans une version Modernizr, et l'option que vous recherchez y est disponible.


Détecter spécifiquement IE

Alternativement , comme user356990 a répondu, vous pouvez utiliser des commentaires conditionnels si vous recherchez uniquement IE et IE. Plutôt que de créer une variable globale, vous pouvez utiliser l'astuce des <html>commentaires conditionnels de HTML5 Boilerplate pour attribuer une classe:

<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->

Si vous avez déjà initialisé jQuery, vous pouvez simplement vérifier avec $('html').hasClass('lt-ie9'). Si vous avez besoin de vérifier la version d'IE dans laquelle vous vous trouvez afin de pouvoir charger sous condition jQuery 1.x ou 2.x, vous pouvez faire quelque chose comme ceci:

myChecks.ltIE9 = (function(){
    var htmlElemClasses = document.querySelector('html').className.split(' ');
    if (!htmlElemClasses){return false;}
    for (var i = 0; i < htmlElemClasses.length; i += 1 ){
      var klass = htmlElemClasses[i];
      if (klass === 'lt-ie9'){
        return true;
      }
    }
    return false;
}());

NB Les commentaires conditionnels d'IE ne sont pris en charge que jusqu'à IE9 inclus. À partir d'IE10, Microsoft encourage l'utilisation de la détection des fonctionnalités plutôt que de la détection du navigateur.


Quelle que soit la méthode que vous choisissez, vous testerez ensuite avec

if ( myChecks.ltIE9 || Modernizr.csstransforms3d ){
    // iframe or flash fallback
} 

Ne prenez pas cela au ||pied de la lettre, bien sûr.

iono
la source
Personnellement, j'essaie toujours de faire une détection basée sur les fonctionnalités plutôt que sur la détection du navigateur
Chris
@Chris C'est bien pour toi, pareil ici? Je ... ne pense pas que vous ayez lu ma réponse.
iono
La vôtre était la première réponse qui suggère en fait d'utiliser la détection de fonctionnalités, donc je pensais que cela pourrait aider une autre personne si elle lisait le commentaire
Chris
@Chris oh, désolé. Je pensais que vous me condamniez pour avoir inclus le test IE.
iono
9

Si vous recherchez une version JS (utilisant une combinaison de détection de fonctionnalités et de reniflage UA) de ce que faisait le passe-partout html5:

var IE = (!! window.ActiveXObject && +(/msie\s(\d+)/i.exec(navigator.userAgent)[1])) || NaN;
if (IE < 9) {
    document.documentElement.className += ' lt-ie9' + ' ie' + IE;
}
Pete B
la source
3

Eh bien, après avoir fait plus de recherches sur ce sujet, j'ai fini par utiliser la solution suivante pour cibler IE 10+. Comme IE10 et 11 sont les seuls navigateurs qui prennent en charge la requête multimédia -ms-high-contrast, c'est une bonne option sans JS:

@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {  
   /* IE10+ specific styles go here */  
}

Fonctionne parfaitement.

Oliver White
la source
2

Les astuces CSS ont une bonne solution pour cibler IE 11:

http://css-tricks.com/ie-10-specific-styles/

Le .NET et Trident / 7.0 sont uniques à IE et peuvent donc être utilisés pour détecter la version 11 d'IE.

Le code ajoute ensuite la chaîne de l'agent utilisateur à la balise html avec l'attribut 'data-useragent', de sorte que IE 11 peut être ciblé spécifiquement ...

Julian Veling
la source
1

J'avais besoin de détecter IE par rapport à presque tout le reste et je ne voulais pas dépendre de la chaîne UA. J'ai trouvé qu'en utilisantes6number avec Modernizr faisait exactement ce que je voulais. Je ne suis pas très préoccupé par ce changement car je ne m'attends pas à ce qu'IE prenne jamais en charge le numéro ES6. Alors maintenant, je connais la différence entre n'importe quelle version d'IE vs Edge / Chrome / Firefox / Opera / Safari.

Plus de détails ici: http://caniuse.com/#feat=es6-number

Notez que je ne suis pas vraiment préoccupé par les faux négatifs d'Opera Mini. Tu pourrais être.

Splaktar
la source
0

Vous pouvez utiliser le < !-- [if IE] > hack pour définir une variable js globale qui sera ensuite testée dans votre code js normal. Un peu moche mais cela a bien fonctionné pour moi.

crazy4groovy
la source
23
Les commentaires conditionnels ne sont plus pris en charge dans Internet Explorer> = 10.
rudimenter