Jquery HTML5类型检测和插件初始化

Jquery HTML5类型检测和插件初始化,jquery,html,fallback,Jquery,Html,Fallback,A部分: 例如,我知道有很多东西可以告诉你一个浏览器是否支持某种HTML5属性,但它们不会告诉你如何从单个元素中获取类型并使用这些信息初始化插件 所以我试着: alert($("input:date")); //returns "[object Object]" alert($("input[type='date']")); //returns "[object Object]" alert($("input").attr("type")); //returns "text" ... w

A部分:

例如,我知道有很多东西可以告诉你一个浏览器是否支持某种HTML5属性,但它们不会告诉你如何从单个元素中获取类型并使用这些信息初始化插件

所以我试着:

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();
警报(输入TTR);
//返回“”
谢谢:

因此,我的第一个问题是: 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>

$(函数(){
var tM=document.createElement(“输入”);
tM.setAttribute(“类型”、“日期”);
如果(tM.type==“文本”){
警报(“浏览器级别不支持日期类型。开始添加日期、周、月和时间回退”);
//谢谢:http://diveintohtml5.ep.io/detect.html
$(“输入”)。每个(函数(){
//如果我们直接从DOM中读取类型属性(某些浏览器),将以文本形式返回未知属性(如第一次检测)。克隆允许我将输入作为变量中的克隆读取。我不知道为什么。
var inputAttr=$('').append($(this.clone()).remove().html().toLowerCase();
警报(输入TTR);
如果(输入索引of(“月”)!=-1)
{
//从元素中获取HTML5属性
var tMmindate=$(this.attr('min');
var tMmaxdate=$(this.attr('max');
//添加带有属性支持且无动画的datepicker(因此我们可以为ie使用-ms过滤器渐变)
$(此).datepick({
渲染器:$.datepick.weekOfYearRenderer,
onShow:$.datepick.monthOnly,
minDate:tMmindate,
maxDate:tMmaxdate,
日期格式:“yyyy-mm”,
showAnim:“}”;
}
其他的
{
$(this.css('border','5px实心红色');
//测试更多输入类型并对其应用init
}
});         
}
});
实例:

还有一个问题: 有人能帮我在HTML5输入类型修复程序中减掉一些脂肪吗

我已经关闭了功能(向IE6-IE8和FF添加了回退,但没有向的init off添加类)

对于神秘的输入类型,是否有更有效的方法在DOM上进行迭代? 在我的示例中,我应该使用If-Else、函数或case吗

谢谢大家


Joel

类型属性不是“组合”元素,它在此处定义:

…而浏览器只“知道”那里定义的@type值(除非他们知道HTML5——HTML5定义了一些新值,如“日期”、“电子邮件”等)

当您查询type属性时,一些浏览器会向您返回“text”,因为如果浏览器不支持“date”类型(或任何它不理解的内容),那么它会返回默认值,即type=“text”

您是否考虑过在输入中添加一个类名(class=“date”),然后只需$(“.date”)。each()然后在该集合上执行检测,您无法在不支持该设置的浏览器中获取type=“date”。如果浏览器检测到一个类型属性,但它不理解该属性,它会用type=“text”(默认值)覆盖该属性

解决这个问题的一种方法(使用jQuery)是简单地添加类日期

然后你可以做类似的事情

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

检测受支持的输入类型的一种更优越的方法是简单地创建一个输入元素,循环所有不同的可用输入类型,并检查
类型
更改是否持续:

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
输入类型的可用性,并通过此操作进行回退。请参见此处的简单演示:。您也可以考虑使用更健壮的HTML5特征检测。
最后,获得
outerHTML
的更好方法是,信不信由你,使用
outerHTML
。而不是

var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase();
(是的,正如您所看到的,有一个警告-
outerHTML
不受Firefox支持,因此我们需要一个简单的解决方法,从)


编辑:从以下页面找到了一个测试本机表单UI支持的方法:。以某种方式支持这些类型的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%可靠-这只适用于对其值有一定限制的类型,而且肯定不是很好,但这是朝着正确方向迈出的一步,现在肯定会解决您的问题


在这里查看更新的演示:

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

Jque
var inputAttr = this.outerHTML || new XMLSerializer().serializeToString(this);
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;
    }
}
 if (elem[ name ] !== undefined)
 {
    return elem[name];
 }
 else
 {
    return elem.getAttribute( 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
   (function() {
        var el = document.createElement('input'),
            notADateValue = 'not-a-date';
        el.setAttribute('type','date');
        el.setAttribute('value', notADateValue);
        return el.value !== notADateValue;
    })();
// 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 );
    }
}
/*
 * 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 
    }
});