html5.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /**
  2. * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
  3. */
  4. ;(function(window, document) {
  5. /*jshint evil:true */
  6. /** version */
  7. var version = '3.7.3';
  8. /** Preset options */
  9. var options = window.html5 || {};
  10. /** Used to skip problem elements */
  11. var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
  12. /** Not all elements can be cloned in IE **/
  13. var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
  14. /** Detect whether the browser supports default html5 styles */
  15. var supportsHtml5Styles;
  16. /** Name of the expando, to work with multiple documents or to re-shiv one document */
  17. var expando = '_html5shiv';
  18. /** The id for the the documents expando */
  19. var expanID = 0;
  20. /** Cached data for each document */
  21. var expandoData = {};
  22. /** Detect whether the browser supports unknown elements */
  23. var supportsUnknownElements;
  24. (function() {
  25. try {
  26. var a = document.createElement( 'a' );
  27. a.innerHTML = '<xyz></xyz>';
  28. // if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
  29. supportsHtml5Styles = ('hidden' in a);
  30. supportsUnknownElements = a.childNodes.length == 1 || (function() {
  31. // assign a false positive if unable to shiv
  32. (document.createElement)('a');
  33. var frag = document.createDocumentFragment();
  34. return (
  35. typeof frag.cloneNode == 'undefined' ||
  36. typeof frag.createDocumentFragment == 'undefined' ||
  37. typeof frag.createElement == 'undefined'
  38. );
  39. }());
  40. } catch (e) {
  41. // assign a false positive if detection fails => unable to shiv
  42. supportsHtml5Styles = true;
  43. supportsUnknownElements = true;
  44. }
  45. }());
  46. /*--------------------------------------------------------------------------*/
  47. /**
  48. * Creates a style sheet with the given CSS text and adds it to the document.
  49. *
  50. * @private
  51. * @param {Document} ownerDocument The document.
  52. * @param {String} cssText The CSS text.
  53. * @returns {StyleSheet} The style element.
  54. */
  55. function addStyleSheet(ownerDocument, cssText) {
  56. var p = ownerDocument.createElement( 'p' ),
  57. parent = ownerDocument.getElementsByTagName( 'head' )[0] || ownerDocument.documentElement;
  58. p.innerHTML = 'x<style>' + cssText + '</style>';
  59. return parent.insertBefore( p.lastChild, parent.firstChild );
  60. }
  61. /**
  62. * Returns the value of `html5.elements` as an array.
  63. *
  64. * @private
  65. * @returns {Array} An array of shived element node names.
  66. */
  67. function getElements() {
  68. var elements = html5.elements;
  69. return typeof elements == 'string' ? elements.split( ' ' ) : elements;
  70. }
  71. /**
  72. * Extends the built-in list of html5 elements
  73. *
  74. * @memberOf html5
  75. * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
  76. * @param {Document} ownerDocument The context document.
  77. */
  78. function addElements(newElements, ownerDocument) {
  79. var elements = html5.elements;
  80. if (typeof elements != 'string') {
  81. elements = elements.join( ' ' );
  82. }
  83. if (typeof newElements != 'string') {
  84. newElements = newElements.join( ' ' );
  85. }
  86. html5.elements = elements + ' ' + newElements;
  87. shivDocument( ownerDocument );
  88. }
  89. /**
  90. * Returns the data associated to the given document
  91. *
  92. * @private
  93. * @param {Document} ownerDocument The document.
  94. * @returns {Object} An object of data.
  95. */
  96. function getExpandoData(ownerDocument) {
  97. var data = expandoData[ownerDocument[expando]];
  98. if ( ! data) {
  99. data = {};
  100. expanID++;
  101. ownerDocument[expando] = expanID;
  102. expandoData[expanID] = data;
  103. }
  104. return data;
  105. }
  106. /**
  107. * returns a shived element for the given nodeName and document
  108. *
  109. * @memberOf html5
  110. * @param {String} nodeName name of the element
  111. * @param {Document|DocumentFragment} ownerDocument The context document.
  112. * @returns {Object} The shived element.
  113. */
  114. function createElement(nodeName, ownerDocument, data) {
  115. if ( ! ownerDocument) {
  116. ownerDocument = document;
  117. }
  118. if (supportsUnknownElements) {
  119. return ownerDocument.createElement( nodeName );
  120. }
  121. if ( ! data) {
  122. data = getExpandoData( ownerDocument );
  123. }
  124. var node;
  125. if (data.cache[nodeName]) {
  126. node = data.cache[nodeName].cloneNode();
  127. } else if (saveClones.test( nodeName )) {
  128. node = (data.cache[nodeName] = data.createElem( nodeName )).cloneNode();
  129. } else {
  130. node = data.createElem( nodeName );
  131. }
  132. // Avoid adding some elements to fragments in IE < 9 because
  133. // * Attributes like `name` or `type` cannot be set/changed once an element
  134. // is inserted into a document/fragment
  135. // * Link elements with `src` attributes that are inaccessible, as with
  136. // a 403 response, will cause the tab/window to crash
  137. // * Script elements appended to fragments will execute when their `src`
  138. // or `text` property is set
  139. return node.canHaveChildren && ! reSkip.test( nodeName ) && ! node.tagUrn ? data.frag.appendChild( node ) : node;
  140. }
  141. /**
  142. * returns a shived DocumentFragment for the given document
  143. *
  144. * @memberOf html5
  145. * @param {Document} ownerDocument The context document.
  146. * @returns {Object} The shived DocumentFragment.
  147. */
  148. function createDocumentFragment(ownerDocument, data) {
  149. if ( ! ownerDocument) {
  150. ownerDocument = document;
  151. }
  152. if (supportsUnknownElements) {
  153. return ownerDocument.createDocumentFragment();
  154. }
  155. data = data || getExpandoData( ownerDocument );
  156. var clone = data.frag.cloneNode(),
  157. i = 0,
  158. elems = getElements(),
  159. l = elems.length;
  160. for (;i < l;i++) {
  161. clone.createElement( elems[i] );
  162. }
  163. return clone;
  164. }
  165. /**
  166. * Shivs the `createElement` and `createDocumentFragment` methods of the document.
  167. *
  168. * @private
  169. * @param {Document|DocumentFragment} ownerDocument The document.
  170. * @param {Object} data of the document.
  171. */
  172. function shivMethods(ownerDocument, data) {
  173. if ( ! data.cache) {
  174. data.cache = {};
  175. data.createElem = ownerDocument.createElement;
  176. data.createFrag = ownerDocument.createDocumentFragment;
  177. data.frag = data.createFrag();
  178. }
  179. ownerDocument.createElement = function(nodeName) {
  180. // abort shiv
  181. if ( ! html5.shivMethods) {
  182. return data.createElem( nodeName );
  183. }
  184. return createElement( nodeName, ownerDocument, data );
  185. };
  186. ownerDocument.createDocumentFragment = Function('h,f', 'return function() {' +
  187. 'var n=f.cloneNode(),c=n.createElement;' +
  188. 'h.shivMethods&&(' +
  189. // unroll the `createElement` calls
  190. getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
  191. data.createElem( nodeName );
  192. data.frag.createElement( nodeName );
  193. return 'c("' + nodeName + '")';
  194. }) +
  195. ');return n}'
  196. )(html5, data.frag);
  197. }
  198. /*--------------------------------------------------------------------------*/
  199. /**
  200. * Shivs the given document.
  201. *
  202. * @memberOf html5
  203. * @param {Document} ownerDocument The document to shiv.
  204. * @returns {Document} The shived document.
  205. */
  206. function shivDocument(ownerDocument) {
  207. if ( ! ownerDocument) {
  208. ownerDocument = document;
  209. }
  210. var data = getExpandoData( ownerDocument );
  211. if (html5.shivCSS && ! supportsHtml5Styles && ! data.hasCSS) {
  212. data.hasCSS = ! ! addStyleSheet(ownerDocument,
  213. // corrects block display not defined in IE6/7/8/9
  214. 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
  215. // adds styling not present in IE6/7/8/9
  216. 'mark{background:#FF0;color:#000}' +
  217. // hides non-rendered elements
  218. 'template{display:none}'
  219. );
  220. }
  221. if ( ! supportsUnknownElements) {
  222. shivMethods( ownerDocument, data );
  223. }
  224. return ownerDocument;
  225. }
  226. /*--------------------------------------------------------------------------*/
  227. /**
  228. * The `html5` object is exposed so that more elements can be shived and
  229. * existing shiving can be detected on iframes.
  230. *
  231. * @type Object
  232. * @example
  233. *
  234. * // options can be changed before the script is included
  235. * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
  236. */
  237. var html5 = {
  238. /**
  239. * An array or space separated string of node names of the elements to shiv.
  240. *
  241. * @memberOf html5
  242. * @type Array|String
  243. */
  244. 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
  245. /**
  246. * current version of html5shiv
  247. */
  248. 'version': version,
  249. /**
  250. * A flag to indicate that the HTML5 style sheet should be inserted.
  251. *
  252. * @memberOf html5
  253. * @type Boolean
  254. */
  255. 'shivCSS': (options.shivCSS !== false),
  256. /**
  257. * Is equal to true if a browser supports creating unknown/HTML5 elements
  258. *
  259. * @memberOf html5
  260. * @type boolean
  261. */
  262. 'supportsUnknownElements': supportsUnknownElements,
  263. /**
  264. * A flag to indicate that the document's `createElement` and `createDocumentFragment`
  265. * methods should be overwritten.
  266. *
  267. * @memberOf html5
  268. * @type Boolean
  269. */
  270. 'shivMethods': (options.shivMethods !== false),
  271. /**
  272. * A string to describe the type of `html5` object ("default" or "default print").
  273. *
  274. * @memberOf html5
  275. * @type String
  276. */
  277. 'type': 'default',
  278. // shivs the document according to the specified `html5` object options
  279. 'shivDocument': shivDocument,
  280. // creates a shived element
  281. createElement: createElement,
  282. // creates a shived documentFragment
  283. createDocumentFragment: createDocumentFragment,
  284. // extends list of elements
  285. addElements: addElements
  286. };
  287. /*--------------------------------------------------------------------------*/
  288. // expose html5
  289. window.html5 = html5;
  290. // shiv the document
  291. shivDocument( document );
  292. if (typeof module == 'object' && module.exports) {
  293. module.exports = html5;
  294. }
  295. }(typeof window !== "undefined" ? window : this, document));