Categories:
Partners

Using document.createElement() to test for browser support for an element

Created: July 12th, 10'

Cross browser scripting is becoming an ever more convoluted game of features versus support. Most of us are familiar with using object detection or the Navigator object to check for backing for a given JavaScript object or method, but these techniques do not work well when the objective is to check whether the browser recognizes a particular HTML element, such as HTML 5's canvas or <input type="datetime" /> element. This is where document.createElement() can be very helpful.

To test for support for an element, the basic premise is this:

  • Use document.createElement() to dynamically create the element as if the browser supports it.

  • Check the newly created object for a known property or JavaScript method that should exist if the browser actually supports this element.

  • For INPUT elements, set its TYPE attribute to the target INPUT TYPE you're testing for, and see if the browser retains that value.

document.createElement() behaves as such that it will create an element regardless of whether the browser actually supports it. The true test on the legitimacy of this newly created element is whether or not it supports the properties and methods expected of it, and that's what we exploit here to test for browser support for an element.

  Checking for support for the canvas element of HTML 5

Lets start our parade of examples with a check for support for the canvas element of HTML 5. Standard object detection doesn't work here, since the canvas element isn't automatically represented by a JavaScript object when the page loads.

var test_canvas = document.createElement("canvas") //try and create sample canvas element
var canvascheck=(test_canvas.getContext)? true : false //check if object supports getContext() method, a method of the canvas element
alert(canvascheck) //alerts true if browser supports canvas element

In the above, first we create a "test" canvas element, then see if it's a legitimate canvas object by checking for the getContext() method, which all canvas capable browsers should have. Canvascheck in turn returns a Boolean indicating whether the browser supports the canvas element of HTML 5.

Checking for support for the audio and video elements of HTML 5

Next up, you can also use document.createElement() to check for support for the new audio and video elements of HTML 5. Both elements once defined support a list of methods, one of which is play(). By fishing for this method in the newly created object, we can check whether the browser actually supports these two elements:

var test_audio= document.createElement("audio") //try and create sample audio element
var test_video= document.createElement("video") //try and create sample video element
var mediasupport={audio: (test_audio.play)? true : false, video: (test_video.play)? true : false}

alert("Audio Element support: " + mediasupport.audio + "\n"
+ "Video Element support: " + mediasupport.video
)

Checking the <style> element for IE behaviors support

Sometimes it's not the element itself you wish to check for, but rather, whether it supports a particular feature. For example, all browsers support the STYLE element, but only IE supports CSS Behaviors, a way to use CSS to add scripting-like behaviors to elements on the page:

<style type="text/css">
.myelement{ behavior:url(test.htc); } </style>

It's a very handy feature, but obviously one that only works in IE. To see if the browser can handle IE behaviors, first, create a "dummy" <style> element, then see if the method addBehavior() exists on it (one of several methods that should be available if the browser is capable):

var dummystyle= document.createElement("style") //try and create sample style element
var behaviortest=(dummystyle.addBehavior)? true : false //check if object supports addBehavior() method

alert(behaviortest) //alerts true if browser supports IE behaviors

Checking the <input> element for HTML5 specific types

HTML5 introduces a slew of new <input> types that go beyond the basic text box to better handle specific tasks. Some of them are:

INPUT TYPE Description Screenshot
<input type="date"> Renders a native date picker to allow users to choose a date from a drop down calendar:
<input type="date" />

Currently only supported in Opera 9+. As of writing, IE8, FF3.7, Safari and Chrome do not yet support it, and will simply render a regular INPUT Text box.


* Screenshot taken in Opera 10.
<input type="datetime"> Renders a native date picker accompanied by a time control:
<input type="datetime" />

Currently only supported in Opera 9+. As of writing, IE8, FF3.7, Safari and Chrome do not yet support it, and will simply render a regular INPUT Text box.


* Screenshot taken in Opera 10.
<input type="range"> Renders a slider to input numbers by dragging a handle left or right:
<input type="range" min="-10" max="10" value="0" step="2" />

Currently supported in Opera 9+, Safari 4+, and Chrome 5+. IE8 and FF3.x do not yet support it.


* Screenshot taken in Chrome 5.0.
<input type="number"> Renders a spinbox for entering a number within a specific range easily:
<input type="number" min="-10" max="10" value="0" step="2" />

Currently only supported in Opera 9+. As of writing, IE8, FF3.7, Safari and Chrome do not yet support it, and will simply render a regular INPUT Text box.


* Screenshot taken in Opera 10.

There are lots of other new HTML5 INPUT elements to play around with, but as you can see, at the moment, it's a rather exclusive playground. So how do check if the browser supports a particular type of INPUT and create an alternate play area for those less fortunate kids? The key lies in the way the "type" attribute of INPUT elements behaves when you attempt to set it using JavaScript- if the browser doesn't support such a type, it won't retain the new value, but instead default to "text" instead. Using this nugget of information, we can test for browser support for any of the new INPUT types. Lets say you want to see if the browser supports <input type="range" />:

var testrange=document.createElement("input")
testrange.setAttribute("type", "range") //set INPUT element to the type we're testing for
if (testrange.type=="range"){
	//browser supports range INPUT!
}

If the browser supports the "range" INPUT, the "type" attribute of our INPUT element will retain that value when we set it, while if not, "text" will be returned instead. Lets do the same now for <input type="date" />:

var testdatepicker=document.createElement("input")
testdatepicker.setAttribute("type", "date") //set INPUT element to the type we're testing for
if (testdatepicker.type=="text"){ //if browser doesn't support INPUT type="calender"
	//implement custom calendar control instead
}

Setting an element's type attribute to the desired value and seeing if it's retained works for any INPUT element you're testing for, though this technique does NOT carry over to all HTML elements. For some elements, the browser will simply hold on to the new value you've set the element's attribute to, so keep this in mind before you go nuts with this technique!

Using document.createElement() to get IE to recognize unknown elements

Whilst on the subject of new elements in HTML5, it's worthwhile to discuss another handy use for document.createElement(), and that's in getting IE to recognise unknown elements (such as many in HTML 5) for the purpose of styling them. You see, in IE (IE6 through IE8), when you include on a page an element the browser doesn't recognize, such as the new <nav> element of HTML5 that's used to contain the main navigational links to the rest of your site, the new element isn't added to the DOM properly, nor can you style it using CSS. That's a problem when you wish to create HTML5 enriched pages that at least degrade well in IE. Fortunately, Sjoerd Visscher discovered an undocumented trick of document.createElement() that takes care of this otherwise debilitating problem. In IE, just by using document.createElement() to dynamically create an instance of an unknown element in the HEAD section of your page forces the element to be properly added to the DOM when you actually define it. You can also style it using CSS so your page holds up in all browsers, old or new.

Here's a simple demonstration of the <nav> element being used on a page, with all browsers including IE recognizing it properly as part of the DOM and applying styling to it:

<head>
<style type="text/css">
nav{
	display:block;
	border:4px solid black;
	margin:10px;
	padding: 10px;
}
</style>

<script type="text/javascript">
	document.createElement("nav")
</script>
</head>
<body>
<nav id="testnav">
	<a href="http://javascriptkit.com">Home</a><br />
	<a href="http://javascriptkit.com/cutpastejava.shtml">Free Scripts</a><br />
	<a href="http://javascriptkit.com/javatutors/">Tutorials</a><br />
</nav>

<p>Welcome to JavaScript Kit</p>

</body>
The single lined script does two things for IE browsers:
  • Gets IE to recognize our <nav> element and correctly represent it within the DOM. Without it, <nav>- or any unrecognized element for that matter- will be inserted as a childless descendant of the BODY element, and probing document.getElementById("testnav").childNodes.length in this instance would return 0 instead of 6.
  • Causes IE to apply any styling directed at the <nav> element instead of ignoring it completely. So in this case, the <nav> element will have a thick black border surrounding it in all browsers.

Before using any new elements of HTML5 on your page, you should follow the same procedure above by dynamically creating that element first using document.createElement() for the sake of IE (up to IE8).