2012-03-29 23:51:39 +01:00
/*! HTML5 Shiv vpre3.5 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */
2012-02-08 14:01:00 +00:00
; ( function ( window , document ) {
/** Preset options */
var options = window . html5 || { } ;
/** Used to skip problem elements */
2012-03-29 23:51:39 +01:00
var reSkip = /^<|^(?:button|form|map|select|textarea|object|iframe)$/i ;
/** Not all elements can be cloned in IE (this list can be shortend) **/
var saveClones = /^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i ;
2012-02-08 14:01:00 +00:00
/** Detect whether the browser supports default html5 styles */
var supportsHtml5Styles ;
/** Detect whether the browser supports unknown elements */
var supportsUnknownElements ;
( function ( ) {
2012-03-29 23:51:39 +01:00
var a = document . createElement ( 'a' ) ;
2012-02-08 14:01:00 +00:00
a . innerHTML = '<xyz></xyz>' ;
2012-03-29 23:51:39 +01:00
//if the hidden property is implemented we can assume, that the browser supports HTML5 Styles | this fails in Chrome 8
supportsHtml5Styles = ( 'hidden' in a ) ;
//if we are part of Modernizr, we do an additional test to solve the Chrome 8 fail
if ( supportsHtml5Styles && typeof injectElementWithStyles == 'function' ) {
injectElementWithStyles ( '#modernizr{}' , function ( node ) {
node . hidden = true ;
supportsHtml5Styles = ( window . getComputedStyle ?
getComputedStyle ( node , null ) :
node . currentStyle ) . display == 'none' ;
} ) ;
}
2012-02-08 14:01:00 +00:00
supportsUnknownElements = a . childNodes . length == 1 || ( function ( ) {
// assign a false positive if unable to shiv
try {
( document . createElement ) ( 'a' ) ;
} catch ( e ) {
return true ;
}
var frag = document . createDocumentFragment ( ) ;
return (
typeof frag . cloneNode == 'undefined' ||
typeof frag . createDocumentFragment == 'undefined' ||
typeof frag . createElement == 'undefined'
) ;
} ( ) ) ;
} ( ) ) ;
/*--------------------------------------------------------------------------*/
/ * *
* Creates a style sheet with the given CSS text and adds it to the document .
* @ private
* @ param { Document } ownerDocument The document .
* @ param { String } cssText The CSS text .
* @ returns { StyleSheet } The style element .
* /
function addStyleSheet ( ownerDocument , cssText ) {
var p = ownerDocument . createElement ( 'p' ) ,
parent = ownerDocument . getElementsByTagName ( 'head' ) [ 0 ] || ownerDocument . documentElement ;
p . innerHTML = 'x<style>' + cssText + '</style>' ;
return parent . insertBefore ( p . lastChild , parent . firstChild ) ;
}
/ * *
* Returns the value of ` html5.elements ` as an array .
* @ private
* @ returns { Array } An array of shived element node names .
* /
function getElements ( ) {
var elements = html5 . elements ;
return typeof elements == 'string' ? elements . split ( ' ' ) : elements ;
}
/ * *
* Shivs the ` createElement ` and ` createDocumentFragment ` methods of the document .
* @ private
* @ param { Document | DocumentFragment } ownerDocument The document .
* /
function shivMethods ( ownerDocument ) {
2012-03-29 23:51:39 +01:00
var cache = { } ,
2012-02-08 14:01:00 +00:00
docCreateElement = ownerDocument . createElement ,
docCreateFragment = ownerDocument . createDocumentFragment ,
2012-03-29 23:51:39 +01:00
frag = docCreateFragment ( ) ;
2012-02-08 14:01:00 +00:00
2012-03-29 23:51:39 +01:00
ownerDocument . createElement = function ( nodeName ) {
//abort shiv
if ( ! html5 . shivMethods ) {
docCreateElement ( nodeName ) ;
}
2012-02-08 14:01:00 +00:00
2012-03-29 23:51:39 +01:00
var node ;
2012-02-08 14:01:00 +00:00
2012-03-29 23:51:39 +01:00
if ( cache [ nodeName ] ) {
node = cache [ nodeName ] . cloneNode ( ) ;
} else if ( saveClones . test ( nodeName ) ) {
node = ( cache [ nodeName ] = docCreateElement ( nodeName ) ) . cloneNode ( ) ;
} else {
node = docCreateElement ( nodeName ) ;
}
// Avoid adding some elements to fragments in IE < 9 because
// * Attributes like `name` or `type` cannot be set/changed once an element
// is inserted into a document/fragment
// * Link elements with `src` attributes that are inaccessible, as with
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
return node . canHaveChildren && ! reSkip . test ( nodeName ) ? frag . appendChild ( node ) : node ;
} ;
ownerDocument . createDocumentFragment = Function ( 'h,f' , 'return function(){' +
'var n=f.cloneNode(),c=n.createElement;' +
'h.shivMethods&&(' +
// unroll the `createElement` calls
getElements ( ) . join ( ) . replace ( /\w+/g , function ( nodeName ) {
docCreateElement ( nodeName ) ;
frag . createElement ( nodeName ) ;
return 'c("' + nodeName + '")' ;
} ) +
');return n}'
) ( html5 , frag ) ;
2012-02-08 14:01:00 +00:00
}
/*--------------------------------------------------------------------------*/
/ * *
* Shivs the given document .
* @ memberOf html5
* @ param { Document } ownerDocument The document to shiv .
* @ returns { Document } The shived document .
* /
function shivDocument ( ownerDocument ) {
var shived ;
if ( ownerDocument . documentShived ) {
return ownerDocument ;
}
if ( html5 . shivCSS && ! supportsHtml5Styles ) {
shived = ! ! addStyleSheet ( ownerDocument ,
// corrects block display not defined in IE6/7/8/9
'article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}' +
// corrects audio display not defined in IE6/7/8/9
'audio{display:none}' +
// corrects canvas and video display not defined in IE6/7/8/9
'canvas,video{display:inline-block;*display:inline;*zoom:1}' +
// corrects 'hidden' attribute and audio[controls] display not present in IE7/8/9
'[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}' +
// adds styling not present in IE6/7/8/9
'mark{background:#FF0;color:#000}'
) ;
}
2012-03-29 23:51:39 +01:00
if ( ! supportsUnknownElements ) {
2012-02-08 14:01:00 +00:00
shived = ! shivMethods ( ownerDocument ) ;
}
if ( shived ) {
ownerDocument . documentShived = shived ;
}
return ownerDocument ;
}
/*--------------------------------------------------------------------------*/
/ * *
* The ` html5 ` object is exposed so that more elements can be shived and
* existing shiving can be detected on iframes .
* @ type Object
* @ example
*
* // options can be changed before the script is included
* html5 = { 'elements' : 'mark section' , 'shivCSS' : false , 'shivMethods' : false } ;
* /
var html5 = {
/ * *
* An array or space separated string of node names of the elements to shiv .
* @ memberOf html5
* @ type Array | String
* /
2012-03-29 23:51:39 +01:00
'elements' : options . elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video' ,
2012-02-08 14:01:00 +00:00
/ * *
* A flag to indicate that the HTML5 style sheet should be inserted .
* @ memberOf html5
* @ type Boolean
* /
'shivCSS' : ! ( options . shivCSS === false ) ,
/ * *
* A flag to indicate that the document ' s ` createElement ` and ` createDocumentFragment `
* methods should be overwritten .
* @ memberOf html5
* @ type Boolean
* /
'shivMethods' : ! ( options . shivMethods === false ) ,
/ * *
* A string to describe the type of ` html5 ` object ( "default" or "default print" ) .
* @ memberOf html5
* @ type String
* /
'type' : 'default' ,
// shivs the document according to the specified `html5` object options
'shivDocument' : shivDocument
} ;
/*--------------------------------------------------------------------------*/
// expose html5
window . html5 = html5 ;
// shiv the document
shivDocument ( document ) ;
} ( this , document ) ) ;