HTML5类型检测和插件初始化

A部分:

我知道有很多东西告诉你浏览器是否支持某个HTML5属性,例如http://diveintohtml5.info/detect.html ,但他们没有告诉你如何从个人获取类型元素并使用该信息来初始化您的插件。

所以我尝试过:

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" 

没有人工作。

我最终想出了这个(确实有效):

 var inputAttr = $('
').append($(this).clone()).remove().html().toLowerCase(); alert(inputAttr); // returns ""

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

所以我的第一个问题:1。为什么我不能在不支持html5的浏览器中读取“type”属性? 您可以组成任何其他属性和虚假值并阅读它。 2.为什么我的解决方案有效? 为什么它在DOM中是否重要?

B部分:

以下是我使用探测器的基本示例:

   $(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 = $('
').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 } }); } });

实例: http : //joelcrawfordsmith.com/sandbox/html5-type-detection.html

一个忙/问:任何人都可以帮我减少HTML5输入法修复器中的一些脂肪吗?

我有function下降(添加回退到IE6-IE8,和FF没有添加类到init关闭)

是否有更有效的方法来迭代DOM以获取神秘输入类型? 我应该在我的例子中使用If Else,函数还是一个案例?

谢谢大家,

乔尔

首先, 停止使用alert进行调试! 获取Firebug和FireQuery的副本,然后使用console.log() 。 即使你正在使用alert() ,你真的应该使用$("input[type='date']").length来查找选择器是否返回任何东西 – object [object]没有告诉你什么在这里很有用


检测支持的输入类型的一个更好的方法是简单地创建一个输入元素并循环遍历所有可用的不同输入类型,并检查type更改是否适用:

 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 } } 

这实际上利用了这样一个事实,即不支持该特定输入类型的浏览器将回退到使用文本,从而允许您测试它们是否受支持。

然后,您可以使用supported['week']来检查week输入类型的可用性,并通过此方式进行回退。 请在此处查看此简单演示: http : //www.jsfiddle.net/yijiang/r5Wsa/2/ 。 您还可以考虑使用Modernizr进行更强大的HTML5function检测。


最后,获得outerHTML的更好方法是,不管你信不信,使用outerHTML 。 代替

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

为什么不使用:

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

(是的,正如您所看到的,有一点需要注意 – Firefox不支持outerHTML ,因此我们需要一个简单的解决方法,来自此Stack Overflow问题 )。


编辑:从此页面找到一种测试本机表单UI支持的方法: http : //miketaylr.com/code/html5-forms-ui-support.html 。 以某种方式支持这些类型的UI的浏览器还应该阻止将无效值输入到这些字段中,因此我们上面所做的测试的逻辑扩展将是这样的:

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

同样,不是100%可靠 – 这只适用于对其价值有一定限制的类型,并且绝对不是很好,但它是朝着正确方向迈出的一步,当然现在可以解决您的问题。

请在此处查看更新的演示: http : //www.jsfiddle.net/yijiang/r5Wsa/3/

要求type属性在所有Android股票浏览器中都不起作用。 他们假装他们支持inputType =“date”,但是他们没有提供日期输入的UI(例如日期选择器)。

此function检测对我有用:

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

诀窍是将非法值设置为日期字段。 如果浏览器清理此输入,它还可以提供日期选择器。

type属性不是“make-up”元素,它在这里定义:

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

…浏览器只“知道”那里定义的@type值(除非它们是HTML5识别的 – 它已经定义了一些新值,如“date”,“email”等)

当您查询type属性时,某些浏览器会向您返回“text”,因为如果浏览器不支持“date”类型(或任何它不理解的东西),那么它会回退到默认值 – 这是type = “文本”

你有没有想过在输入中添加一个类名(class =“date”),然后你可以只用$(’。date’)。each()然后你在那个集合上检测

我认为这是JQuery中的一个错误! 如果你查看JQuery代码本身的attr()函数,JQuery首先尝试使用括号表示法获取传递的名称的值。 如果未定义,则返回该值。 如果未定义,则使用getAttribute()方法。

Jquery为$(“#elem”)执行类似的操作.attr(name):

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

问题是Jquery假设如果elem [name]未定义,那么elem [name]是正确的。

请考虑以下示例:

  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 

传入.attr(“type”)时,myInput [‘type’]返回“text”,因此Jquery返回“text”。 如果你传入.attr(“joel”),myInput [‘joel’]返回undefined,那么Jquery使用getAttribute(’joel’)而不是返回“crawford”。

您不能在不支持此function的浏览器中获取type =“date”。 如果浏览器检测到它不理解的类型属性,则使用type =“text”(默认值)覆盖它。

解决这个问题(使用jQuery)只是添加类日期。

然后你可以做类似的事情

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

只是tester.type = i; 在IE中抛出exception。 固定版本:

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

这是一个jQuery脚本,用于检测浏览器是否支持HTML5日期格式,如果是,则将所有date字段值更改为yyyy-mm-dd格式,并将所有datetime字段值更改为yyyy-mm-dd hh:mm:ss格式。

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