HTML5 type initialization and plugin initialization

PART A:

I know that there are many things that tell you whether the browser supports a specific HTML5 attribute, for example http://diveintohtml5.info/detect.html , but they do not tell you how to get the type from individual elements and use this information to initialize 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" 

No one worked.

In the end, I came up with this (this works):

 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 is: 1. Why can't I read the "type" attribute in browsers that do not support html5? You can compose any other attribute and dummy value and read it. 2. Why does my solution work? Why does it matter if it is in the DOM or not?

PART B:

The following is a basic example of what I use for discovery:

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

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

And the service / question: Can someone help me cut off some fat in my HTML5 type input block?

I have functionality down (adds backups for IE6-IE8 and FF without adding classes for init)

Are there more efficient methods for iterating over the DOM for secret input types? And should I use If If Else, or a function, or a case in my example?

Thanks everyone

Joel

+16
jquery html5 fallback
Nov 11 '10 at 22:20
source share
7 answers

First of all, stop using alert to debug! Take a copy of Firebug and FireQuery and use them with console.log() . Even if you work with alert() , you really need to use $("input[type='date']").length to find if the selector returned something - object [object] does not tell you anything useful here.




A higher method for detecting supported input data types is to simply create an input element and skip all available input data types and check if type changing:

 var supported = {date: false, number: false, time: false, month: false, week: false}, tester = document.createElement('input'); for(var i in supported){ tester.type = i; if(tester.type === i){ supported[i] = true; } } 

This actually exploits the fact that browsers that do not support this type of input return to using text, thereby allowing you to check whether they are supported or not.

Then you can use supported['week'] , for example, to check the availability of the input type week and back up through this. See a simple demonstration of this here: http://www.jsfiddle.net/yijiang/r5Wsa/2/ . You might also consider using Modernizr to more reliably detect HTML5 features.




And finally, the best way to get outerHTML is, believe it or not, use outerHTML . Instead

 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 caution - outerHTML not supported by Firefox, so we will need a simple workaround from this stack. Overflow question ).




Edit: A testing method was found to support the user interface in the native form from this page: http://miketaylr.com/code/html5-forms-ui-support.html . Browsers that support the user interface for these types in some way should also prevent the entry of invalid values โ€‹โ€‹in these fields, so the logical extension for the test, which we do above, will be as follows:

 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 this is a step in the right direction and will certainly solve your problem now.

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

+27
Nov 12 '10 at 2:31
source share

The type attribute request does not work in all Android browsers. They pretend that they support inputType = "date", but they do not offer a user interface (datepicker, for example) for data input.

This detection of this function worked for me:

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

The trick is to set an invalid value in the date field. If the browser sanitizes this input, it may also offer a dumper.

+7
Oct 09 '13 at 14:14
source share

The type attribute is not a make-up element, which is defined here:

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

... and browsers only โ€œknowโ€ about the @type values โ€‹โ€‹defined there (unless they know HTML5), which defined some new values, such as โ€œdateโ€, โ€œemailโ€, etc.)

When you request a type attribute, some browsers return a "text" to you, because if the browser does not support the "date" type (or something that it does not understand), then it returns to the default value - which is type = "text "

Have you thought about adding a class name (class = "date") to the inputs, and then you can just $ ('. Date'). each () and then you discover on this set

+3
Nov 12 2018-10-11T00:
source share

I would say that this is a bug in jQuery! If you look at the attr () function in the jQuery code itself, jQuery will first try to get the value for the name that you passed with the notation bracket. If it is not undefined, then it returns this value. If it is undefined, then the getAttribute () method is used instead.

JQuery does something similar to this for $ ("# elem"). attr (name):

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

The problem is that jquery accepts, if elem [name] is not undefined, then elem [name] is correct.

Consider the following example:

 <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 

When you go into .attr ("type"), myInput ['type'] returns "text", so jQuery returns "text". If you switched to .attr ("joel"), myInput ['joel'] returns undefined, so Jquery instead uses getAttribute ('joel'), which returns "crawford".

+3
Nov 18 '10 at 17:50
source share

You cannot get type = "date" in a browser that does not support this. If the browser detects a type attribute, it does not understand that it overrides it with type = "text" (default).

The way to this (using jQuery) is to simply add the class date.

Then you can do something like

 $('input.date').each(function() { var $this = $(this); if($this.attr('type') != 'date') $this.datepicker(); }); 
+1
Nov 12 2018-10-12T00:
source share

Just tester.type = i; throws an exception in IE. Fixed Version:

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

Always check, never blindly copy-paste!

0
Mar 06 '17 at 13:54 on
source share

Here's a jQuery script that determines whether the browser supports HTML5 date format, and if so, it changes all the values โ€‹โ€‹of the date fields in the yyyy-mm-dd format, and all the datetime fields are equal to yyyy-mm-dd hh:mm:ss format .

 // 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 ); } } 
0
Dec 27 '17 at 7:47
source share



All Articles