嘗試偵測瀏覽器對於html5 tag的支援

 Wed, 29 Sep 2010 16:16:55 +0800

為了要學習html5新規格,一個方法就是利用寫程式的機會來熟悉,所以就想寫個小程式來偵測html5規格中定義的tag。 最早的想法,是用document.createElement(),傳入規格書裡面規定的tagName,看看產生物件會不會出問題,但結果是...一律不會出問題 (汗)。(如果是xml,我用任何自訂的tag都不應該有問題,是我太天真)所以看起來還需要加不少工。更可靠的方式,是判斷產生出來的物件,是否有該有的property。這個可以用這些property是否為undefined來判斷,需要的話,還可以賦值,看看會不會產生錯誤。依照這個想法,寫了一個簡單的程式來判斷瀏覽器對於html5規格中定義的tag,支援如何:(放在首頁太長了,所以請進入觀看 :-D)

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery-1.4.2.min.js"></script>
<script>
$(document).ready(function(){
  function row(cells) {
    return '<tr>' + cells.join('') + '</tr>\n';
  }
  function cell(text, style, col) {
    return '<td' + (col? ' colspan="'+col+'"':'') + (style? ' style="'+style+'"':'') + '>' + text + '</td>';
  }
  var tags = {
    '4.1 The root element' : [
      {'tagName':'html','attr':['lang','manifest']}
    ],
    '4.2 Document metadata' : [
      {'tagName':'head','attr':[]},
      {'tagName':'title','attr':['text']},
      {'tagName':'base','attr':['href','target']},
      {'tagName':'link','attr':['disabled','href','rel','relList','media','hreflang','type','sizes','title']},
      {'tagName':'meta','attr':['name','httpEquiv','content','charset']},
      {'tagName':'style','attr':['disabled','media','type','scoped','title']}
    ],
    '4.3 Scripting' : [
      {'tagName':'script','attr':['src','async','defer','type','charset','text']},
      {'tagName':'noscript','attr':[]}
    ],
    '4.4 Sections' : [
      {'tagName':'body','attr':['onafterprint','onbeforeprint','onbeforeunload','onblur','onerror','onfocus','onhashchange','onload','onmessage','onoffline','ononline','onpagehide','onpageshow','onpopstate','onredo','onresize','onstorage','onundo','onunload']},
      {'tagName':'section','attr':[]},
      {'tagName':'nav','attr':[]},
      {'tagName':'article','attr':[]},
      {'tagName':'aside','attr':[]},
      {'tagName':'h1','attr':[]},
      {'tagName':'h2','attr':[]},
      {'tagName':'h3','attr':[]},
      {'tagName':'h4','attr':[]},
      {'tagName':'h5','attr':[]},
      {'tagName':'h6','attr':[]},
      {'tagName':'hgroup','attr':[]},
      {'tagName':'header','attr':[]},
      {'tagName':'footer','attr':[]},
      {'tagName':'address','attr':[]}
    ],
    '4.5 Grouping content' : [
      {'tagName':'p','attr':[]},
      {'tagName':'hr','attr':[]},
      {'tagName':'pre','attr':[]},
      {'tagName':'blockquote','attr':['cite']},
      {'tagName':'ol','attr':['reversed','start']},
      {'tagName':'ul','attr':[]},
      {'tagName':'li','attr':['value']},
      {'tagName':'dl','attr':[]},
      {'tagName':'dt','attr':[]},
      {'tagName':'dd','attr':[]},
      {'tagName':'figure','attr':[]},
      {'tagName':'figcaption','attr':[]},
      {'tagName':'div','attr':[]}
    ],
    '4.6 Text-level semantics' : [
      {'tagName':'a','attr':['href','target','rel','relList','media','hreflang','type','text','protocol','host','hostname','port','pathname','search','hash']},
      {'tagName':'em','attr':[]},
      {'tagName':'strong','attr':[]},
      {'tagName':'small','attr':[]},
      {'tagName':'cite','attr':[]},
      {'tagName':'q','attr':['cite']},
      {'tagName':'dfn','attr':['title']},
      {'tagName':'abbr','attr':['title']},
      {'tagName':'time','attr':['dateTime','pubDate','valueAsDate']},
      {'tagName':'code','attr':[]},
      {'tagName':'var','attr':[]},
      {'tagName':'samp','attr':[]},
      {'tagName':'kbd','attr':[]},
      {'tagName':'sub','attr':[]},
      {'tagName':'sup','attr':[]},
      {'tagName':'i','attr':[]},
      {'tagName':'b','attr':[]},
      {'tagName':'mark','attr':[]},
      {'tagName':'ruby','attr':[]},
      {'tagName':'rt','attr':[]},
      {'tagName':'rp','attr':[]},
      {'tagName':'bdo','attr':['dir']},
      {'tagName':'span','attr':[]},
      {'tagName':'br','attr':[]},
      {'tagName':'wbr','attr':[]}
    ],
    '4.7 Edits' : [
      {'tagName':'ins','attr':['cite','datetime']},
      {'tagName':'del','attr':['cite','datetime']}
    ],
    '4.8 Embedded content' : [
      {'tagName':'img','attr':['alt','src','useMap','isMap','width','height','naturalWidth','naturalHeight','complete']},
      {'tagName':'iframe','attr':['src','srcdoc','name','sandbox','seamless','width','height','contentDocument','contentWindow']},
      {'tagName':'embed','attr':['src','type','width','height']},
      {'tagName':'object','attr':['data','type','name','useMap','form','width','height','contentDocument','contentWindow','willValidate','validity','validationMessage','chechValidity','setCustomValidity']},
      {'tagName':'param','attr':['name','value']},
      {'tagName':'video','attr':['src','poster','preload','autoplay','loop','controls','width','height','videoWidth','videoHeight']},
      {'tagName':'audio','attr':['src','preload','autoplay','loop','controls']},
      {'tagName':'source','attr':['src','type','media']},
      {'tagName':'canvas','attr':['width','height','toDataURL','getContext']},
      {'tagName':'map','attr':['name','areas','images']},
      {'tagName':'area','attr':['alt','coords','shape','href','target','rel','relList','media','hreflang','type','protocol','host','hostname','port','pathname','search','hash']}
    ],
    '4.9 Tabular data' : [
      {'tagName':'table','attr':['summary','caption','createCaption','deleteCaption','tHead','createTHead','deleteTHead','tFoot','createTFoot','deleteTFoot','tBodies','createTBody','rows','insertRow','deleteRow']},
      {'tagName':'caption','attr':[]},
      {'tagName':'colgroup','attr':['span']},
      {'tagName':'col','attr':['span']},
      {'tagName':'tbody','attr':['rows','insertRow','deleteRow']},
      {'tagName':'thead','attr':[]},
      {'tagName':'tfoot','attr':[]},
      {'tagName':'tr','attr':['rowIndex','sectionRowIndex','cells','insertCell','deleteCell']},
      {'tagName':'td','attr':['colspan','rowspan','headers']},
      {'tagName':'th','attr':['colspan','rowspan','headers','scope']}
    ],
    '4.10 Forms' : [
      {'tagName':'form','attr':['acceptCharset','action','autocomplete','enctype','method','name','noValidate','target','elements','length','item','namedItem','submit','reset','checkValidity','dispatchFormInput','dispatchFormChange']},
      {'tagName':'fieldset','attr':['disabled','form','name','type','elements','willValidate','validity','validationMessage','checkValidity','setCustomValidity']},
      {'tagName':'legend','attr':['form']},
      {'tagName':'label','attr':['form','htmlFor','control']},
      {'tagName':'input','attr':['type=hidden','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=text','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=search','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=tel','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=url','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=email','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=password','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=datetime','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=date','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=month','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=week','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=time','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=datetime-local','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=number','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=range','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=color','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=checkbox','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=radio','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=file','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=submit','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=image','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=reset','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'input','attr':['type=button','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'button','attr':['autofocus','disabled','form','formAction','formEnctype','formMethod','formNoValidate','formTarget','name','type','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels']},
      {'tagName':'select','attr':['autofocus','disabled','form','multiple','name','size','type','options','length','item','namedItem','add','remove','selectedOptions','selectedIndex','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels']},
      {'tagName':'datalist','attr':['options']},
      {'tagName':'optgroup','attr':['disabled','label']},
      {'tagName':'option','attr':['disabled','form','label','defaultSelected','selected','value','text','index']},
      {'tagName':'textarea','attr':['autofocus','cols','disabled','form','maxLength','name','placeHolder','readOnly','required','rows','wrap','type','defaultValue','value','textLength','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange']},
      {'tagName':'keygen','attr':['autofocus','challenge','disabled','form','keytype','name','type','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels']},
      {'tagName':'output','attr':['htmlFor','form','name','type','defaultValue','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels']},
      {'tagName':'progress','attr':['value','max','position','form','labels']},
      {'tagName':'meter','attr':['value','min','max','low','high','optimum','form','labels']}
    ],
    '4.11 Interactive elements' : [
      {'tagName':'details','attr':['open']},
      {'tagName':'summary','attr':[]},
      {'tagName':'command','attr':['type','label','icon','disabled','checked','radiogroup','title']},
      {'tagName':'menu','attr':['type','label']}
    ]
  },
  str = '';
  str += '<table cellpadding="3" cellspacing="0" border="1" width="100%">';
  for(var i in tags) {
    str += row([cell(i, 'background:#E0E0EF', 2)]);
    for(var j=0; j<tags[i].length; j++) {
      var result = false;
      try {
        var tmp = document.createElement(tags[i][j].tagName);
        if(tags[i][j].attr.length>0) {
          for(var k=0; k<tags[i][j].attr.length; k++) {
            if(tags[i][j].attr[k].indexOf('=')>-1) {
              var fields = tags[i][j].attr[k].split('=');
              if(tmp[fields[0]] !== undefined) {
                tmp[fields[0]] = fields[1];
                result = true;
              }
            } else {
              if(tmp[tags[i][j].attr[k]] !== undefined)
                result = true;
            }
          }
        } else {
          result = true;
        }
      } catch(e) {
      } finally {
        str += row(
          [
            cell('<strong>'+tags[i][j].tagName+'</strong>'+' <sub>['+tags[i][j].attr.join(', ')+']</sub>'),
            cell(
              '<strong>'+(result? 'yes':'no')+'</strong>',
              (result? 'background:#60DF60':'background:#DF6060')+';width:50px'
            )
          ]
        );
      }
    }
  }
  $('#panel').html(str+'</table>');
});
</script>
</head>
<body>
<div id="panel"></div>
</body>
</html>

測試的結果,還是Chrome最好,Firefox4差距也不太大,IE9則...還是有些差距。下面是一些測試截圖:

Chrome6問題最少

Firefox4也不錯

IE9有許多input type不支援

IE9其他部份算是OK

這是Opera

這是Safari

不過顯示 no 也不一定代表真的不支援,只是一些property的支援不完整就是了。另外,這個小程式還有進步空間,首先是應該根據DOM Interface之間的繼承關係,來比較完整地偵測property是否支援。另外可能就是根據html5規格裡面提到的一些content model規則以及其他特徵,來做一些檢測。


2010-10-15 1:15 補充:

稍微修改程式,加入對於HTMLElement共通屬性的偵測。經過簡單測試,看起來contentEditable屬性在所有支援HTML5的瀏覽器上,他標籤相對應的DOM鍵都有支援,所以就使用他了:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery-1.4.2.min.js"></script>
<script>
$(document).ready(function(){
  function row(cells) {
    return '<tr>' + cells.join('') + '</tr>\n';
  }
  function cell(text, style, col) {
    return '<td' + (col? ' colspan="'+col+'"':'') + (style? ' style="'+style+'"':'') + '>' + text + '</td>';
  }
  var tags = {
    '4.1 The root element' : [
      {'tagName':'html','attr':['lang','manifest','contentEditable']}
    ],
    '4.2 Document metadata' : [
      {'tagName':'head','attr':['contentEditable']},
      {'tagName':'title','attr':['text','contentEditable']},
      {'tagName':'base','attr':['href','target','contentEditable']},
      {'tagName':'link','attr':['disabled','href','rel','relList','media','hreflang','type','sizes','title','contentEditable']},
      {'tagName':'meta','attr':['name','httpEquiv','content','charset','contentEditable']},
      {'tagName':'style','attr':['disabled','media','type','scoped','title','contentEditable']}
    ],
    '4.3 Scripting' : [
      {'tagName':'script','attr':['src','async','defer','type','charset','text','contentEditable']},
      {'tagName':'noscript','attr':['contentEditable']}
    ],
    '4.4 Sections' : [
      {'tagName':'body','attr':['onafterprint','onbeforeprint','onbeforeunload','onblur','onerror','onfocus','onhashchange','onload','onmessage','onoffline','ononline','onpagehide','onpageshow','onpopstate','onredo','onresize','onstorage','onundo','onunload','contentEditable']},
      {'tagName':'section','attr':['contentEditable']},
      {'tagName':'nav','attr':['contentEditable']},
      {'tagName':'article','attr':['contentEditable']},
      {'tagName':'aside','attr':['contentEditable']},
      {'tagName':'h1','attr':['contentEditable']},
      {'tagName':'h2','attr':['contentEditable']},
      {'tagName':'h3','attr':['contentEditable']},
      {'tagName':'h4','attr':['contentEditable']},
      {'tagName':'h5','attr':['contentEditable']},
      {'tagName':'h6','attr':['contentEditable']},
      {'tagName':'hgroup','attr':['contentEditable']},
      {'tagName':'header','attr':['contentEditable']},
      {'tagName':'footer','attr':['contentEditable']},
      {'tagName':'address','attr':['contentEditable']}
    ],
    '4.5 Grouping content' : [
      {'tagName':'p','attr':['contentEditable']},
      {'tagName':'hr','attr':['contentEditable']},
      {'tagName':'pre','attr':['contentEditable']},
      {'tagName':'blockquote','attr':['cite','contentEditable']},
      {'tagName':'ol','attr':['reversed','start','contentEditable']},
      {'tagName':'ul','attr':['contentEditable']},
      {'tagName':'li','attr':['value','contentEditable']},
      {'tagName':'dl','attr':['contentEditable']},
      {'tagName':'dt','attr':['contentEditable']},
      {'tagName':'dd','attr':['contentEditable']},
      {'tagName':'figure','attr':['contentEditable']},
      {'tagName':'figcaption','attr':['contentEditable']},
      {'tagName':'div','attr':['contentEditable']}
    ],
    '4.6 Text-level semantics' : [
      {'tagName':'a','attr':['href','target','rel','relList','media','hreflang','type','text','protocol','host','hostname','port','pathname','search','hash','contentEditable']},
      {'tagName':'em','attr':['contentEditable']},
      {'tagName':'strong','attr':['contentEditable']},
      {'tagName':'small','attr':['contentEditable']},
      {'tagName':'cite','attr':['contentEditable']},
      {'tagName':'q','attr':['cite','contentEditable']},
      {'tagName':'dfn','attr':['title','contentEditable']},
      {'tagName':'abbr','attr':['title','contentEditable']},
      {'tagName':'time','attr':['dateTime','pubDate','valueAsDate','contentEditable']},
      {'tagName':'code','attr':['contentEditable']},
      {'tagName':'var','attr':['contentEditable']},
      {'tagName':'samp','attr':['contentEditable']},
      {'tagName':'kbd','attr':['contentEditable']},
      {'tagName':'sub','attr':['contentEditable']},
      {'tagName':'sup','attr':['contentEditable']},
      {'tagName':'i','attr':['contentEditable']},
      {'tagName':'b','attr':['contentEditable']},
      {'tagName':'mark','attr':['contentEditable']},
      {'tagName':'ruby','attr':['contentEditable']},
      {'tagName':'rt','attr':['contentEditable']},
      {'tagName':'rp','attr':['contentEditable']},
      {'tagName':'bdo','attr':['dir']},
      {'tagName':'span','attr':['contentEditable']},
      {'tagName':'br','attr':['contentEditable']},
      {'tagName':'wbr','attr':['contentEditable']}
    ],
    '4.7 Edits' : [
      {'tagName':'ins','attr':['cite','datetime','contentEditable']},
      {'tagName':'del','attr':['cite','datetime','contentEditable']}
    ],
    '4.8 Embedded content' : [
      {'tagName':'img','attr':['alt','src','useMap','isMap','width','height','naturalWidth','naturalHeight','complete','contentEditable']},
      {'tagName':'iframe','attr':['src','srcdoc','name','sandbox','seamless','width','height','contentDocument','contentWindow','contentEditable']},
      {'tagName':'embed','attr':['src','type','width','height','contentEditable']},
      {'tagName':'object','attr':['data','type','name','useMap','form','width','height','contentDocument','contentWindow','willValidate','validity','validationMessage','chechValidity','setCustomValidity','contentEditable']},
      {'tagName':'param','attr':['name','value','contentEditable']},
      {'tagName':'video','attr':['src','poster','preload','autoplay','loop','controls','width','height','videoWidth','videoHeight','contentEditable']},
      {'tagName':'audio','attr':['src','preload','autoplay','loop','controls','contentEditable']},
      {'tagName':'source','attr':['src','type','media','contentEditable']},
      {'tagName':'canvas','attr':['width','height','toDataURL','getContext','contentEditable']},
      {'tagName':'map','attr':['name','areas','images','contentEditable']},
      {'tagName':'area','attr':['alt','coords','shape','href','target','rel','relList','media','hreflang','type','protocol','host','hostname','port','pathname','search','hash','contentEditable']}
    ],
    '4.9 Tabular data' : [
      {'tagName':'table','attr':['summary','caption','createCaption','deleteCaption','tHead','createTHead','deleteTHead','tFoot','createTFoot','deleteTFoot','tBodies','createTBody','rows','insertRow','deleteRow','contentEditable']},
      {'tagName':'caption','attr':['contentEditable']},
      {'tagName':'colgroup','attr':['span','contentEditable']},
      {'tagName':'col','attr':['span','contentEditable']},
      {'tagName':'tbody','attr':['rows','insertRow','deleteRow','contentEditable']},
      {'tagName':'thead','attr':['contentEditable']},
      {'tagName':'tfoot','attr':['contentEditable']},
      {'tagName':'tr','attr':['rowIndex','sectionRowIndex','cells','insertCell','deleteCell','contentEditable']},
      {'tagName':'td','attr':['colspan','rowspan','headers','contentEditable']},
      {'tagName':'th','attr':['colspan','rowspan','headers','scope','contentEditable']}
    ],
    '4.10 Forms' : [
      {'tagName':'form','attr':['acceptCharset','action','autocomplete','enctype','method','name','noValidate','target','elements','length','item','namedItem','submit','reset','checkValidity','dispatchFormInput','dispatchFormChange','contentEditable']},
      {'tagName':'fieldset','attr':['disabled','form','name','type','elements','willValidate','validity','validationMessage','checkValidity','setCustomValidity','contentEditable']},
      {'tagName':'legend','attr':['form','contentEditable']},
      {'tagName':'label','attr':['form','htmlFor','control','contentEditable']},
      {'tagName':'input','attr':['type=hidden','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=text','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=search','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=tel','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=url','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=email','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=password','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=datetime','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=date','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=month','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=week','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=time','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=datetime-local','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=number','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=range','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=color','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=checkbox','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=radio','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=file','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=submit','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=image','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=reset','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'input','attr':['type=button','accept','alt','autocomplete','autofocus','defaultChecked','checked','disabled','form','files','formAction','formEnctype','formMethod','formNoValidate','formTarget','height','indeterminate','list','max','maxLength','min','multiple','name','pattern','placeholder','readOnly','required','size','src','step','defaultValue','value','valueAsDate','valueAsNumber','selectedOption','width','stepUp','stepDown','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'button','attr':['autofocus','disabled','form','formAction','formEnctype','formMethod','formNoValidate','formTarget','name','type','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','contentEditable']},
      {'tagName':'select','attr':['autofocus','disabled','form','multiple','name','size','type','options','length','item','namedItem','add','remove','selectedOptions','selectedIndex','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','contentEditable']},
      {'tagName':'datalist','attr':['options','contentEditable']},
      {'tagName':'optgroup','attr':['disabled','label','contentEditable']},
      {'tagName':'option','attr':['disabled','form','label','defaultSelected','selected','value','text','index','contentEditable']},
      {'tagName':'textarea','attr':['autofocus','cols','disabled','form','maxLength','name','placeHolder','readOnly','required','rows','wrap','type','defaultValue','value','textLength','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','select','selectionStart','selectionEnd','setSelectionRange','contentEditable']},
      {'tagName':'keygen','attr':['autofocus','challenge','disabled','form','keytype','name','type','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','contentEditable']},
      {'tagName':'output','attr':['htmlFor','form','name','type','defaultValue','value','willValidate','validity','validationMessage','checkValidity','setCustomValidity','labels','contentEditable']},
      {'tagName':'progress','attr':['value','max','position','form','labels','contentEditable']},
      {'tagName':'meter','attr':['value','min','max','low','high','optimum','form','labels','contentEditable']}
    ],
    '4.11 Interactive elements' : [
      {'tagName':'details','attr':['open','contentEditable']},
      {'tagName':'summary','attr':['contentEditable']},
      {'tagName':'command','attr':['type','label','icon','disabled','checked','radiogroup','title','contentEditable']},
      {'tagName':'menu','attr':['type','label','contentEditable']}
    ]
  },
  str = '';
  str += '<table cellpadding="3" cellspacing="0" border="1" width="100%">';
  for(var i in tags) {
    str += row([cell(i, 'background:#E0E0EF', 2)]);
    for(var j=0,x=tags[i].length; j<x; j++) {
      var result = false;
      try {
        var tmp = document.createElement(tags[i][j].tagName);
        tmp['data-test'] = 'test-value';
        if(tags[i][j].attr.length>0) {
          for(var k=0,y=tags[i][j].attr.length; k<y; k++) {
            if(tags[i][j].attr[k].indexOf('=')>-1) {
              var fields = tags[i][j].attr[k].split('=');
              if(tmp[fields[0]] !== undefined) {
                tmp[fields[0]] = fields[1];
                result = true;
              }
            } else {
              if(tmp[tags[i][j].attr[k]] !== undefined)
                result = true;
            }
          }
        } else {
          result = true;
        }
      } catch(e) {
      } finally {
        str += row(
          [
            cell('<strong>'+tags[i][j].tagName+'</strong>'+' <sub>['+tags[i][j].attr.join(', ')+']</sub>'),
            cell(
              '<strong>'+(result? 'yes':'no')+'</strong>',
              (result? 'background:#60DF60':'background:#DF6060')+';width:50px'
            )
          ]
        );
      }
    }
  }
  $('#panel').html(str+'</table>');
});
</script>
</head>
<body>
<div id="panel"></div>
</body>
</html>

另外,目前看起來,除了IE9 Beta,其他瀏覽器的最新版本已經完整支援所有HTML5標籤。(細節就不管了)