HTML5类型检测和插件初始化

时间:2010-11-11 22:20:26

标签: jquery html5 fallback

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

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

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

B部分:

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

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

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

赞成/问题: 任何人都可以帮我在我的HTML5输入类型修复器中减少一些脂肪吗?

我的功能有所下降(为IE6-IE8添加了回退,而FF没有向init添加类)

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

全部谢谢,

乔尔

8 个答案:

答案 0 :(得分:26)

首先,停止使用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进行更强大的HTML5功能检测。


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

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

为什么不使用:

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

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


编辑:从此页面找到一种测试本机表单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/

答案 1 :(得分:9)

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

此功能检测对我有用:

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

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

答案 2 :(得分:3)

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

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

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

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

您是否考虑过在输入中添加一个类名(class =“date”),然后您可以只使用$('。date')。each()然后在该集上检测

答案 3 :(得分:3)

我认为这是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]是正确的。

考虑以下示例:

<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

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

答案 4 :(得分:0)

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

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

然后你可以做类似

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

答案 5 :(得分:0)

Just tester.type = i;在IE中抛出异常。修正版:

&#13;
&#13;
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());
&#13;
&#13;
&#13;

始终测试,绝不盲目复制粘贴!

答案 6 :(得分:0)

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

yyyy-mm-dd hh:mm:ss

答案 7 :(得分:0)

好的,我认为此处描述的检测浏览器是否支持日期输入类型的方法过于复杂,如果您想要更简单的方法,您可以执行以下操作:

/*
 * Instead of body, you could use the closest parent where you know your input is going to be 
 */
$("body").on("focus", "input[type='date']", function(){
    let attribute, property;
    attribute= $(this).attr("type").toUpperCase();
    property= $(this).prop("type").toUpperCase();
    if(attribute!== property){
        console.log("This browser doe not support type='date'");
        //Pop up your own calendar or use a plugin 
    }
});

这个函数会在你聚焦一个 type="date" 的 input 时执行,如果它在页面上不存在也没关系,监听器会一直监听直到有新的 input[type="date" ] 在 body 上,但正如评论中所建议的,如果您有一个更近的容器,并且您知道它将始终包含输入,那么您可以更改它而不是“body”。

无论如何 JS 监听器都很快