2010-11-11 15 views
16

PARTE A:HTML5 Detección Tipo y Plugin de inicialización

Sé que hay un montón de cosas por ahí que le indican si un navegadorsoporta un determinado atributo de HTML 5, por ejemplo http://diveintohtml5.info/detect.html, pero don' Te digo cómo adquirir el tipo de elementos individuales y usar esa información para iniciar tus complementos.

así que he intentado:

alert($("input:date")); 
//returns "[object Object]" 

alert($("input[type='date']")); 
//returns "[object Object]" 

alert($("input").attr("type")); 
//returns "text" ... which is a lie. it should have been "date" 

Ninguno aquellos trabajó.

finalmente se me ocurrió esto (que funciona):

var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 
alert(inputAttr); 
// returns "<input min="-365" max="365" type="date">" 

Gracias: http://jquery-howto.blogspot.com/2009/02/how-to-get-full-html-string-including.html

Así que mi primera pregunta: 1. ¿Por qué no puedo leer el atributo "tipo" en navegadores que no son compatibles con html5? Puedes inventar cualquier otro atributo y valor falso y leerlo. 2. ¿Por qué funciona mi solución? ¿Por qué importa si está en DOM o no?

PARTE B:

A continuación se muestra un ejemplo básico de lo que estoy utilizando el detector para:

<script type="text/javascript" > 
    $(function() { 
    var tM = document.createElement("input"); 
    tM.setAttribute("type", "date"); 
     if (tM.type == "text") { 
      alert("No date type support on a browser level. Start adding date, week, month, and time fallbacks"); 
     // Thanks: http://diveintohtml5.ep.io/detect.html 

      $("input").each(function() { 
       // If we read the type attribute directly from the DOM (some browsers) will return unknown attributes as text (like the first detection). Making a clone allows me to read the input as a clone in a variable. I don't know why. 
       var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 

        alert(inputAttr); 

        if (inputAttr.indexOf("month") !== -1) 

        { 
         //get HTML5 attributes from element 
         var tMmindate = $(this).attr('min'); 
         var tMmaxdate = $(this).attr('max'); 
         //add datepicker with attributes support and no animation (so we can use -ms-filter gradients for ie) 
         $(this).datepick({ 
          renderer: $.datepick.weekOfYearRenderer, 
          onShow: $.datepick.monthOnly, 
          minDate: tMmindate, 
          maxDate: tMmaxdate, 
          dateFormat: 'yyyy-mm', 
          showAnim: ''}); 
        } 
        else 
        { 

         $(this).css('border', '5px solid red'); 
         // test for more input types and apply init to them 
        } 

       });   
      } 
     }); 

     </script> 

ejemplo vivo: http://joelcrawfordsmith.com/sandbox/html5-type-detection.html

Y un favor/pregunta: Puede Alguien me ayuda a cortar un poco de grasa en mi fixer de tipo de entrada HTML5?

tengo la funcionalidad hacia abajo (fallbacks añade a IE6-IE8, FF y con la adición de clases a cabo a init fuera de)

¿Existen métodos más eficientes para la iteración en el DOM para los tipos de entrada de misterio? ¿Y debería usar un If Else, o una función, o un caso en mi ejemplo?

Gracias a todos,

Joel

Respuesta

3

El atributo de tipo no es un elemento "maquillada", se define aquí:

http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.4

... y los navegadores única " saber "sobre los valores @type definidos allí (a menos que estén conscientes de HTML5 - que ha definido algunos valores nuevos como" fecha "," correo electrónico ", etc.)

Cuando consulta el atributo de tipo algunos navegadores le devuelven "texto" porque si un navegador no admite el tipo "fecha" (o cualquier cosa que no comprenda), vuelve al valor predeterminado, que es type = "texto"

¿Ha pensado añadir un nombre de clase (clase = "fecha") a las entradas y luego puede simplemente $ ('fecha'). cada() y luego hacer la detección en ese conjunto

+0

¡Oh ciertamente! No pretendo sugerir que el atributo de tipo no sea real. Estaba preguntando por qué no puede devolver el valor de tipo de la misma manera que podría devolver un atributo inventado. –

+0

Pensé en solo agregar la clase, pero quería tener una alternativa completa. –

1

No puede obtener type = "date" en un navegador que no es compatible con esto.Si un navegador detecta un atributo de tipo que no comprende, lo anula con el tipo = "texto" (predeterminado).

Una forma de evitar esto (usando jQuery) es simplemente agregar la fecha de clase también.

entonces usted puede hacer algo como

$('input.date').each(function() { 
    var $this = $(this); 
    if($this.attr('type') != 'date') $this.datepicker(); 
}); 
+1

Realmente puede obtener el atributo tipo en jQuery, de eso se trata mi publicación y prueba. Esperaba que alguien pudiera explicar por qué son necesarios los trucos que debemos realizar para leer el atributo tipo. –

+0

Eso no es "obtener" el tipo, es decir, obtener el html original y "mirar" el tipo. No puedes consultar eso. – Alxandr

+0

Creo que puede estar equivocado al respecto. En IE11, tanto en el escritorio como en el teléfono, devuelvo la "fecha" de usar jQuery para obtener el tipo de entrada, pero ninguno proporciona una plataforma que proporcione el selector de fecha. –

27

En primer lugar, dejar de usar alert hacer su depuración! Tome una copia de Firebug y FireQuery y utilícelos con console.log(). Incluso si está trabajando con alert(), realmente debería utilizar $("input[type='date']").length para encontrar si el selector devolvió algo: object [object] no le dice nada útil aquí.


Un método muy superior para la detección de tipos de entrada soportados es simplemente crear un elemento de entrada y el bucle a través de todos los diferentes tipos de entrada disponibles y comprobar si los palos type cambio:

var supported = { date: false, number: false, time: false, month: false, week: false }, 
    tester = document.createElement('input'); 

for (var i in supported){ 
    try { 
     tester.type = i; 
     if (tester.type === i){ 
      supported[i] = true; 
     } 
    } catch (e) { 
     // IE raises an exception if you try to set the type to 
     // an invalid value, so we just swallow the error 
    } 
} 

En realidad, esto hace uso del hecho de que los navegadores que no son compatibles con ese tipo de entrada particular recurrirán al uso de texto, lo que le permite probar si son compatibles o no.

Puede usar supported['week'], por ejemplo, para verificar la disponibilidad del tipo de entrada week, y hacer sus retrocesos a través de esto. Vea una demostración simple de esto aquí: http://www.jsfiddle.net/yijiang/r5Wsa/2/. También puede considerar usar Modernizr para una detección de funciones HTML5 más robusta.


Y, por último, una mejor manera de conseguir outerHTML es, lo creas o no, utilizar outerHTML. En lugar de

var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 

Por qué no utilizar:

var inputAttr = this.outerHTML || new XMLSerializer().serializeToString(this); 

(Sí, como se puede ver, hay una advertencia - outerHTML no es compatible con Firefox, por lo que vamos a necesitar una solución simple, desde this Stack Overflow question).


Editar: encontrado un método para hacer pruebas para el apoyo de IU forma nativa, de esta página: http://miketaylr.com/code/html5-forms-ui-support.html. Los navegadores que soportan la interfaz de usuario para este tipo de alguna manera debe también evitar que los valores no válidos a partir sido introducidos en estos campos, por lo que la extensión lógica de la prueba que estamos haciendo anterior sería la siguiente:

var supported = {date: false, number: false, time: false, month: false, week: false}, 
    tester = document.createElement('input'); 

for(var i in supported){ 
    tester.type = i; 
    tester.value = ':('; 

    if(tester.type === i && tester.value === ''){ 
     supported[i] = true; 
    } 
} 

Una vez más, no es 100% confiable, esto solo es bueno para los tipos que tienen ciertas restricciones en sus valores, y definitivamente no es muy bueno, pero es un paso en la dirección correcta, y ciertamente resolvería su problema ahora.

Véase la actualización de demostración aquí: http://www.jsfiddle.net/yijiang/r5Wsa/3/

+0

¡Gracias por su respuesta detallada! Ha proporcionado información muy útil para ayudarme a hacer el guion más eficiente al usar más JS en lugar de jQuery.Exactamente el tipo de información que estaba buscando. ¿Podría darme algunas aclaraciones sobre un par de artículos? ¿De qué manera la muestra del código de detección de tipo de entrada permite que los navegadores antiguos sean valores de atributo de tipo HTML5 no soportados? Ese es mi objetivo. detección eficiente de valores no soportados ... no solo detecta soporte (como lo hace Modernizr). Tal vez estoy malinterpretando el propósito de las muestras. ¡Gracias de nuevo! –

+0

@Joel No intenta emular el comportamiento del navegador más antiguo, porque tiene esa parte hecha correctamente. Es la parte de detección de características lo que creo que es problemático: sé que estás tratando de usar el selector de atributos para esto, pero en realidad en general hay un mejor identificador para estos elementos de formulario, por ejemplo, 'id' que se requiere para' etiqueta para trabajar. Analizar el HTML del elemento 'input' es una solución muy sucia aquí. –

+0

Es bastante irónico que el código utilizado para detectar las características modernas del navegador no funcione si el navegador no es compatible con las características modernas del navegador (var ... in .. sintaxis). El violín no funciona en IE 11, que admite la fecha de entrada ... –

3

Yo diría que esto es un error en jQuery! Si observa la función attr() en el código JQuery, JQuery primero intenta obtener un valor para el nombre que pasó usando la notación de corchetes. Si no está indefinido, entonces devuelve ese valor. Si no está definido, entonces usa el método getAttribute().

Jquery hace algo similar a esto por $ ("# elem") attr (nombre):.

if (elem[ name ] !== undefined) 
{ 
    return elem[name]; 
} 
else 
{ 
    return elem.getAttribute(name) 
} 

El problema es Jquery está asumiendo si elem [nombre] no está definida, entonces Elem [ nombre] es correcto.

Consideremos el siguiente ejemplo:

<input type="date" id="myInput" name="myInput" joel="crawford" />  

var myInput = document.getElementById('myInput'); 

alert(myInput['type']);//returns text  
alert(myInput.getAttribute('type'));//returns date 
alert($("#myInput").attr('type'));//returns text 

alert(myInput['joel']);//returns undefined 
alert(myInput.getAttribute('joel'));//returns crawford 
alert($("#myInput").attr('joel'));//returns crawford 

Cuando se pasa en .attr ("tipo"), myInput [ 'type'] volverá "texto", por lo que vuelve Jquery "texto". Si pasó en .attr ("joel"), myInput ['joel'] devuelve indefinido, entonces Jquery usa getAttribute ('joel') en su lugar, que devuelve "crawford".

7

Preguntar por el atributo de tipo no funciona en todos los navegadores de Android. Fingen que admiten inputType = "date", pero no ofrecen una UI (datepicker, por ejemplo) para las entradas de fecha.

Esta detección de características trabajó para mí:

(function() { 
     var el = document.createElement('input'), 
      notADateValue = 'not-a-date'; 
     el.setAttribute('type','date'); 
     el.setAttribute('value', notADateValue); 
     return el.value !== notADateValue; 
    })(); 

El truco es fijar un valor no válido en un campo de fecha. Si el navegador desinfecta esta entrada, también podría ofrecer un marcador de fecha.

0

Just tester.type = i; throws exception in IE. versión fija:

var get_supported_html5_input_types = function() { 
 
    var supported = { 
 
      date: false, 
 
      number: false, 
 
      time: false, 
 
      datetime: false, 
 
      'datetime-local':false, 
 
      month: false, 
 
      week: false 
 
     }, 
 
     tester = document.createElement('input'); 
 
    for(var i in supported){ 
 
     // Do nothing - IE throws, FF/Chrome just ignores 
 
     try { tester.type = i; } catch (err) {} 
 
     if(tester.type === i){ 
 
      supported[i] = true; 
 
     } 
 
    } 
 
    return supported; 
 
}; 
 

 
console.log(get_supported_html5_input_types());

prueba siempre, nunca ciegamente copiar y pegar!

0

Aquí es un script de jQuery que detecta si el navegador es compatible con HTML5 formato date, y si es así, cambia todos los valores de campo date a yyyy-mm-dd formato, y todos los valores de campo datetime a yyyy-mm-dd hh:mm:ss formato.

// From https://stackoverflow.com/a/10199306 
// If the browser supports HTML5 input type="date", change all the values from y/m/dddd format to yyyy-mm-dd format, so they appear properly: 
function fix_date_inputs() { 
    try { 
     var input = document.createElement('input'); 
     input.setAttribute('type','date'); 

     var notADateValue = 'not-a-date'; 
     input.setAttribute('value', notADateValue); 

     var r = (input.value !== notADateValue); 

     if (r) { 
      $('input').each(function() { 
       if (
        $(this).attr('type').match(/^date/) // date or datetime 
       ) { 
        var m_d_y = $(this).context.attributes.value.value; // Because $(this).val() does not work (returns '') 

        var d = new Date(m_d_y); 

        var month = '' + (d.getMonth() + 1); 
        var day = '' + d.getDate(); 
        var year = d.getFullYear(); 

        if (month.length < 2) month = '0' + month; 
        if (day.length < 2) day = '0' + day; 

        var yyyy_mm_dd = [ year, month, day ].join('-'); 

        // If we're processing a datetime, add the time: 
        if (
         $(this).attr('type') == 'datetime' 
        ) { 
         var h = '' + d.getHours(); 
         var i = '' + d.getMinutes(); 
         var s = '' + d.getSeconds(); 

         if (h.length < 2) h = '0' + h; 
         if (i.length < 2) i = '0' + i; 
         if (s.length < 2) s = '0' + s; 

         yyyy_mm_dd += ' ' + [ h, i, s ].join(':'); 
        } 

        $(this).val(yyyy_mm_dd); // Here, val() works to set the new value. Go figure. 
       } 
      }); 

     } 
    } catch(e) { 
     alert('Internal error: ' + e.message); 
    } 
} 
Cuestiones relacionadas