¿Forma correcta de usar Modernizr para detectar IE?

84

Quería usar la biblioteca Modernizr JS para detectar algunas propiedades del navegador para determinar qué contenido mostrar o no mostrar.

Tengo una aplicación llamada Pano2VR que genera HTML5 y SWF. Necesito HTML5 para usuarios de dispositivos iOS.

Sin embargo, IE no muestra esta salida "HTML5" en absoluto. Parece que su salida usa transformaciones CSS3 3D y WebGL, una o más aparentemente no son compatibles con IE9.

Entonces, para esos usuarios, necesito mostrar la versión Flash. Estaba planeando usar un IFRAME y pasar el SRC a través de un script o documento de Modernizr. Escriba el código IFRAME correcto según el navegador.

Todo lo cual lleva a cómo utilizo Modernizr para detectar simplemente IE o no IE? ¿O detectar transformaciones CSS 3D?

¿O hay otra manera de hacer esto?

Steve
fuente

Respuestas:

1

Estoy de acuerdo en que deberíamos probar las capacidades, pero es difícil encontrar una respuesta simple a "¿qué capacidades son compatibles con los 'navegadores modernos' pero no con los 'navegadores antiguos'?"

Así que encendí varios navegadores e inspeccioné Modernizer directamente. Agregué algunas capacidades que definitivamente necesito, y luego agregué "inputtypes.color" porque parece cubrir todos los principales navegadores que me interesan: Chrome, Firefox, Opera, Edge ... y NO IE11. Ahora puedo sugerir suavemente que el usuario estaría mejor con Chrome / Opera / Firefox / Edge.

Esto es lo que yo uso: puede editar la lista de cosas para probar en su caso particular. Devuelve falso si falta alguna de las capacidades.

/**
 * 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;
}

Y aquí está el método GetProperty que se necesita para "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
fuente
195

Modernizr no detecta los navegadores como tales, detecta qué característica y capacidad están presentes y esto es todo lo que está tratando de hacer.

Podría intentar conectar un script de detección simple como este y luego usarlo para hacer su elección. También he incluido la detección de versiones por si fuera necesario. Si solo desea verificar cualquier versión de IE, puede buscar navigator.userAgent con un valor de "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>");

Luego, simplemente puede verificar:

BrowserDetect.browser == 'Explorer';
BrowserDetect.version <= 9;
Código de forma única
fuente
2
Gracias. Finalmente terminé rastreando que el problema era que su archivo necesitaba soporte webgl. Entonces, podría usar Modernizer para probar eso y hacer un document.write de un bloque de código del otro. Pero esta es una excelente solución para la detección de navegadores. Gracias de nuevo.
Steve
2
Una cosa para recordar: la cadena UA es completamente configurable por el usuario. Por lo tanto, verificar la cadena UA NO es una forma consistente de verificar el navegador. developer.mozilla.org/en-US/docs/DOM/window.navigator.userAgent En la sección "Notas":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
Sí, pero ¿qué porcentaje de usuarios navega por la web con una cadena UA modificada / falsificada / incorrecta? ¿Cuánto tiempo de ingeniería desea dedicar a garantizar que una pequeña minoría tenga una experiencia óptima en su sitio? El rastreo del navegador a través de una cadena UA es un enfoque práctico y sensato.
Jed Richards
17
@Wintamute, no puedo estar más de acuerdo. Hartate de la clase de conferencia "la detección de características es mala". Estamos haciendo ingeniería, no buscando arte
Philip007
9
Es la suposición general de que si alguien modifica su cadena UA, entonces sabe lo que está haciendo y puede lidiar con las consecuencias. De hecho, esto es exactamente para lo que existe la cadena UA: para declarar la versión del navegador al servidor. Si el cliente quiere mentir sobre eso, entonces, ¡así es la vida! Por supuesto, existe una pequeña posibilidad de que la cadena se cambie sin el consentimiento del usuario, pero en la práctica eso no es una preocupación real, y ¿se supone que debemos alimentar al usuario y frotarle la espalda también?
Rolf
20

Puede usar Modernizr para detectar simplemente IE o no, comprobando el soporte de animación SVG SMIL .

Si ha incluido la detección de características SMIL en su configuración de Modernizr, puede usar un enfoque CSS simple y apuntar a la clase .no-smil que Modernizr aplica al elemento html :

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

Alternativamente, puede usar Modernizr con un enfoque simple de JavaScript, así:

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

Tenga en cuenta que IE / Edge algún día podría admitir SMIL , pero actualmente no hay planes para hacerlo.

Como referencia, aquí hay un enlace a la tabla de compatibilidad de SMIL en caniuse.com .

jacefarm
fuente
La mejor respuesta en mi opinión. Tan simple
Batman
2
Si bien esto funciona, funciona por ahora. El objetivo de la detección de funciones y Modernizr es que no tiene que preocuparse por lo que suceda mañana. Si Edge se actualiza mañana con soporte smil, su código ya no funciona y es posible que ni siquiera lo sepa.
Jason
Sigue siendo que no hay planes para el soporte de SMIL en Edge .
jacefarm
1
Esto parecía tan simple, pero aparentemente Edge ahora es compatible con SMIL .
Jeremy Carlson
12

Detectando transformaciones CSS 3D

Modernizr puede detectar transformaciones CSS 3D , sí. La veracidad de Modernizr.csstransforms3dle dirá si el navegador los admite.

El enlace anterior le permite seleccionar qué pruebas incluir en una compilación de Modernizr, y la opción que está buscando está disponible allí.


Detectando IE específicamente

Alternativamente , como respondió el usuario 356990, puede usar comentarios condicionales si está buscando solo IE e IE. En lugar de crear una variable global, puede usar el <html>truco de comentarios condicionales de HTML5 Boilerplate para asignar una clase:

<!--[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 ya ha inicializado jQuery, puede consultar con $('html').hasClass('lt-ie9'). Si necesita verificar en qué versión de IE se encuentra para poder cargar condicionalmente jQuery 1.xo 2.x, puede hacer algo como esto:

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

Nota: los comentarios condicionales de IE solo se admiten hasta IE9 inclusive. Desde IE10 en adelante, Microsoft fomenta el uso de la detección de funciones en lugar de la detección del navegador.


Cualquiera que sea el método que elija, lo probará con

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

No te lo tomes ||literalmente, por supuesto.

iono
fuente
En lo personal yo siempre trato de hacer la detección basada función en lugar de la detección del navegador
Chris
@Chris Bien por ti, ¿lo mismo aquí? Yo ... no creo que hayas leído mi respuesta.
iono
La suya fue la primera respuesta que en realidad sugiere usar la función de detección, así que pensé que podría ayudar a otra persona si leían el comentario
Chris
@Chris oh, lo siento. Pensé que me condenabas por incluir el examen IE.
iono
9

Si está buscando una versión JS (usando una combinación de detección de características y rastreo de UA) de lo que solía hacer html5 boilerplate:

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
fuente
3

Bueno, después de investigar más sobre este tema, terminé usando la siguiente solución para apuntar a IE 10+. Como IE10 y 11 son los únicos navegadores que admiten la consulta de medios -ms-high-contrast, esa es una buena opción sin JS:

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

Funciona perfectamente.

Oliver White
fuente
2

Los trucos CSS tienen una buena solución para apuntar a IE 11:

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

.NET y Trident / 7.0 son exclusivos de IE, por lo que se pueden utilizar para detectar la versión 11 de IE.

El código luego agrega la cadena de agente de usuario a la etiqueta html con el atributo 'data-useragent', por lo que IE 11 puede ser dirigido específicamente ...

Julian Veling
fuente
1

Necesitaba detectar IE frente a casi todo lo demás y no quería depender de la cadena UA. Descubrí que usar es6numbercon Modernizr hizo exactamente lo que quería. No me preocupa mucho este cambio, ya que no espero que IE admita el Número ES6. Así que ahora sé la diferencia entre cualquier versión de IE vs Edge / Chrome / Firefox / Opera / Safari.

Más detalles aquí: http://caniuse.com/#feat=es6-number

Tenga en cuenta que no me preocupan mucho los falsos negativos de Opera Mini. Usted podría ser.

Splaktar
fuente
0

Puede usar el < !-- [if IE] > truco para establecer una variable js global que luego se prueba en su código js normal. Un poco feo pero me ha funcionado bien.

crazy4groovy
fuente
23
Los comentarios condicionales no son más compatibles con Internet Explorer> = 10.
rudimenter