Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
541 views
in Technique[技术] by (71.8m points)

jquery - HTML5 Type Detection and Plugin Initialization

PART A:

I know there are a lot of things out there that tell you if a browser supports a certain HTML5 attribute, for example http://diveintohtml5.info/detect.html, but they don't tell you how to acquire the type from individual elements and use that info to init your plugins.

So I tried:

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"

None those worked.

I eventually came up with this (that does work):

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

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

So my first question: 1. Why can I not read the "type" attribute in browsers that don't support html5? You can make up any other attribute and bogus value and read it. 2. Why does my solution work? Why does it matter if its in the DOM or not?

PART B:

Below is a basic example of what I am using the detector for:

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

Live example: http://joelcrawfordsmith.com/sandbox/html5-type-detection.html

And a favor/question: Can anyone help me cut some fat in my HTML5 input type fixer?

I have the functionality down (adds fallbacks to IE6-IE8, and FF with out adding classes to init off of)

Are there are more efficient methods for iterating over the DOM for mystery input types? And should I be using an If Else, or a function, or a case in my example?

Thanks All,

Joel

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A far superior method for detecting supported input types is to simply create an input element and loop through all of the different input types available and check if the type change sticks:

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

This actually makes use of the fact that browsers which do not support that particular input type will fall back to using text, thereby allowing you to test if they're supported or not.

You can then use supported['week'], for instance, to check for the availability of the week input type, and do your fallbacks through this. See a simple demo of this here: http://www.jsfiddle.net/yijiang/r5Wsa/2/. You might also consider using Modernizr for more robust HTML5 feature detection.


And finally, a better way to get outerHTML is to, believe it or not, use outerHTML. Instead of

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

Why not just use:

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

(Yes, as you can see, there is a caveat - outerHTML isn't supported by Firefox, so we're going to need a simple workaround, from this Stack Overflow question).


Edit: Found a method to do testing for native form UI support, from this page: http://miketaylr.com/code/html5-forms-ui-support.html. Browsers that support the UI for these types in some way should also prevent invalid values from been entered into these fields, so the logical extension to the test we're doing above would be 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;
    }
}

Again, not 100% reliable - this is only good for types that have certain restrictions on their values, and definitely not very good, but it's a step in the right direction, and certainly would solve your problem now.

See the updated demo here: http://www.jsfiddle.net/yijiang/r5Wsa/3/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...