2013-08-13 25 views
9

Korzystanie z JavaScript, czy możliwe jest uzyskanie listy znaczników obsługiwanych przez przeglądarkę?Wszystkie znaczniki HTML obsługiwane przez przeglądarkę

+1

co by było używane? – twinlakes

+5

@programminginallston Aby naprawić ciekawość OP. Mam nadzieję, że OP nie jest kotem ... – dc5

+0

Nie widzę tu ważnego przypadku użycia. Czy możesz wyjaśnić, co masz nadzieję osiągnąć? –

Odpowiedz

4

Można dostać przyzwoity pomysł, co jest obsługiwany przez introspekcji w oknie.

Spróbuj tego:

props = Object.getOwnPropertyNames(window) 
for (var idx in props) { 
    if (props[idx].indexOf("HTML") == 0) { 
    //do something here 
    console.log(props[idx]); 
    } 
} 

To jest w żaden sposób wyczerpujący o ile wiem, ale powie to, co w większości przeglądarek znaczniki mają typ obiektu DOM.

Oto przykładowe dane wyjściowe, uruchamiając w moim konsoli Chrome:

HTMLUnknownElement 
HTMLOptionsCollection 
HTMLFormControlsCollection 
HTMLAllCollection 
HTMLCollection 
HTMLUListElement 
HTMLTitleElement 
HTMLTextAreaElement 
HTMLTemplateElement 
HTMLTableSectionElement 
HTMLTableRowElement 
HTMLTableElement 
HTMLTableColElement 
HTMLTableCellElement 
HTMLTableCaptionElement 
HTMLStyleElement 
HTMLSpanElement 
HTMLSelectElement 
HTMLScriptElement 
HTMLQuoteElement 
HTMLProgressElement 
HTMLPreElement 
HTMLParamElement 
HTMLParagraphElement 
HTMLOutputElement 
HTMLOptionElement 
HTMLOptGroupElement 
HTMLObjectElement 
HTMLOListElement 
HTMLModElement 
HTMLMeterElement 
HTMLMetaElement 
HTMLMenuElement 
HTMLMarqueeElement 
HTMLMapElement 
HTMLLinkElement 
HTMLLegendElement 
HTMLLabelElement 
HTMLLIElement 
HTMLKeygenElement 
HTMLInputElement 
HTMLImageElement 
HTMLIFrameElement 
HTMLHtmlElement 
HTMLHeadingElement 
HTMLHeadElement 
HTMLHRElement 
HTMLFrameSetElement 
HTMLFrameElement 
HTMLFormElement 
HTMLFontElement 
HTMLFieldSetElement 
HTMLEmbedElement 
HTMLDivElement 
HTMLDirectoryElement 
HTMLDataListElement 
HTMLDListElement 
HTMLCanvasElement 
HTMLButtonElement 
HTMLBodyElement 
HTMLBaseElement 
HTMLBRElement 
HTMLAreaElement 
HTMLAppletElement 
HTMLAnchorElement 
HTMLElement 
HTMLDocument 
+2

Jest to interesujące, ale daje listę interfejsów, a nie listę typów elementów. Na przykład lista nie zawiera niczego, co odpowiada "strong" lub "span", ponieważ te elementy nie mają własnych interfejsów (po prostu używają ogólnego interfejsu HTMLElement). –

+0

Co mogę zobaczyć, prawdopodobnie nie jest to niezawodny sposób, ale podoba mi się ta metoda, ponieważ może być używana bez listy startowej i, jak mówi @ JukkaK.Korpela, na liście będą dziury, jest wciąż całkiem fajną metodą. – Hugo

5

Jeśli jesteś gotów do rozpoczęcia ze znanym liście tagów kandydujących, można spróbować czegoś takiego:

document.createElement("asdf") instanceof HTMLUnknownElement 
true 
document.createElement("canvas") instanceof HTMLUnknownElement 
false 

Jeśli trzeba wspierać IE8, można użyć tego podejścia:

function browserSupports(elementTagName) { 
    var el = document.createElement(elementTagName); 
    return !((el instanceOf HTMLUnknownElement) || (el instanceof HTMLGenericElement)); 
} 

Oto inne podejście, które nie polega na konkretnych nazwanych konstruktorach.

function browserSupports(elementTagName) { 
    var unknownel = document.createElement("zzxcv"); 
    var el = document.createElement(elementTagName); 
    return unknownel.constructor !== el.constructor; 
} 

Mimo to nadal nie działa w IE8.

+1

Nie jest to w pełni niezawodne, ponieważ stare przeglądarki nie rozpoznają "HTMLUnknownElement". I testując w ten sposób z IE 10 w trybie IE 8, otrzymuję wynik 'false' jeśli testuję obsługę * dowolnego * elementu (włączając elementy, które są z pewnością obsługiwane, jak' p'). –

+0

@ JukkaK.Korpela: Dobra uwaga. Dodałem nową implementację, która obsługuje IE8. – recursive

+0

Mój oryginalny pomysł polegał na tym, aby nie używać znaczników list, ale jest to również całkiem fajne podejście =). – Hugo

3

Nie ma ogólny sposób, ale każdy element ma specyficzny sposób, aby sprawdzić, czy jest obsługiwana

Canvas wsparcie elementem:

var canvasSupported = "getContext" in document.createElement("canvas"); 

Rodzaj wejścia wsparcia:

var input = document.createElement("input"); 
input.type = "color" 
var colorInputSupported = input.type === "color"; 
//The above relies on the fact that type is enumerated and 
//falls back to "text" with invalid value 
//The technique doesn't necessarily carry over to other properties 

wsparcie elementem audio:

var audioElementSupported = "play" in document.createElement("audio"); 

Progress element nośny

var progressElementSupported = "max" in document.createElement("progress"); 
+0

Rzeczywiście jest to zależne od elementu. Na przykład technika używana do obsługi typu "input" nie powiedzie się, jeśli spróbujesz zastosować ją do testowania wsparcia dla 'align = char' dla' td' (wynik jest prawdziwy, nawet jeśli żadna przeglądarka faktycznie nie obsługuje tej wartości). –

+0

@ JukkaK.Korpela Tak, nie chciałem sugerować, że technika testowania typu "input" przenosi się na cokolwiek innego. Działa to specjalnie dlatego, że 'type' jest wyliczonym atrybutem. Wyjaśniłem to w edycji. – Esailija

+0

Atrybut "wyrównaj" jest również wyliczany. Nawet atrybuty, które są formalnie podobne (z wyliczoną listą wartości), mogą być różnie traktowane przez przeglądarkę. –

0

Every JavaScript html elementem obiektu, stworzony przez document.createElement(), posiada funkcję konstruktora, który zawsze zaczyna się od " HTML ... "i kończy się na" ... Element ". Wszystkie te są dziedziczone z HTMLElement. Każdy z nich jest dostępny w obiekcie window poprzez Object.getOwnPropertyNames().

Dzięki temu można uzyskać wszystkie prawidłowe nazwy znaczników przez iterowanie wszystkich nazw właściwości w oknie i filtrowanie ich za pomocą kodu HTML ...Element:

function getAllTagNames() 
{ 
    let names = []; 

    Object.getOwnPropertyNames(window).forEach(name => 
    { 
     if(name.startsWith('HTML') && name.endsWith('Element') && Object.getPrototypeOf(window[name]) == HTMLElement) 
     { 
      names.push(name.substr(4, name.length - 11).toLowerCase()); 
     } 
    }); 

    names.sort((left, right) => 
    { 
     if(left.toLowerCase) { left = left.toLowerCase(); } 
     if(right.toLowerCase) { right = right.toLowerCase(); } 

     return left == right ? 0 : (left < right ? -1 : 1); 
    }); 

    return names; 
} 

Jak go używać:

console.log(getAllTagNames()); // [anchor", "area", "base", "body", "br", ...] 

edit

Niektóre funkcje konstruktora dla elementów HTML są tylko bazowe funkcje konstruktora (np HTMLMediaElement). W tym przypadku funkcja konstruktora baza HTMLAudioElement (< dźwięku > </audio >) i HTMLVideoElement (< video> </video >) nie są bezpośrednio dziedziczyć HTMLElement. Więc jest to niezbędne do uruchomienia za pośrednictwem całego łańcucha ProType The instanceof operator nadaje się do tego:

window['HTMLAudioElement'].prototype instanceof HTMLElement 

Innym aspektem jest to, że niektóre nazwy funkcji konstruktora nie pasuje do równoważnej nazwy znacznika html (< > => HTML Kotwica Element) i niektóre inne nazwy zmieścić kilka tagów (np < h1 > </h1 >, < h2 >do/H2 >, < H3 > </H3 >, < H4 > </H4 >, < H5 > </H5 >, < H6 > </H6 >) o tej samej funkcji konstruktora. > see mdn.

Obecnie nie ma innego sposobu na javscript stworzyć złą Nazwa zidentyfikowanego znacznik z document.createElement (Zmienna) ;, sprawdź czy konstruktor jest HTMLUnknownElement i utrwalano je ręcznie:

function getAllTagNames() 
{ 
    let items = []; 

    Object.getOwnPropertyNames(window).forEach(name => 
    { 
     if(name.startsWith('HTML') && name.endsWith('Element') && window[name].prototype instanceof HTMLElement) 
     { 
      items.push({ constructorName: name, tagName: name.substr(4, name.length - 11).toLowerCase() }); 
     } 
    }); 

    items.sort((leftItem, rightItem) => 
    { 
     let left = leftItem.tagName; 
     let right = rightItem.tagName; 

     if(left.toLowerCase) { left = left.toLowerCase(); } 
     if(right.toLowerCase) { right = right.toLowerCase(); } 

     return left == right ? 0 : (left < right ? -1 : 1); 
    }); 

    function insertSorted(item) 
    { 
     let index = 0; 
     while(item.tagName > items[index].tagName) { index++; } 
     items.splice(index, 0, item); 
    } 

    let disagreements = []; 
    items = items.filter(item => 
    { 
     let tagName = item.tagName; 

     switch(tagName) // deprecated 
     { 
      case "keygen": return false; 
     } 

     let filter = tagName == "unknown" || document.createElement(tagName).constructor == HTMLUnknownElement; 
     if(filter && tagName != "unknown") { disagreements.push(item); } 

     return !filter; 
    }); 

    disagreements = disagreements.filter(item => 
    { 
     switch(item.tagName) // base constructor 
     { 
      case "media": return false; 
     } 

     return true; 
    }); 

    disagreements.forEach(item => 
    { 
     let tagName = item.tagName; 

     function exchange(tagName) 
     { 
      insertSorted({ constructorName: item.constructorName, tagName: tagName }); 
     } 

     switch(tagName) 
     { 
      case 'anchor': 
       exchange('a'); 
       break; 

      case 'directory': 
       exchange('dir'); 
       break; 

      case 'dlist': 
       exchange('dl'); 
       break; 

      case 'heading': 
       exchange('h1'); 
       exchange('h2'); 
       exchange('h3'); 
       exchange('h4'); 
       exchange('h5'); 
       exchange('h6'); 
       break; 

      case 'image': 
       exchange('img'); 
       break; 

      case 'mod': 
       exchange('del'); 
       exchange('ins'); 
       break; 

      case 'olist': 
       exchange('ol'); 
       break; 

      case 'paragraph': 
       exchange('p'); 
       break; 

      case 'quote': 
       exchange('blockquote'); 
       exchange('q'); 
       break; 

      case 'tablecaption': 
       exchange('caption'); 
       break; 

      case 'tablecell': 
       exchange('th'); 
       exchange('td'); 
       break; 

      case 'tablecol': 
       exchange('col'); 
       exchange('colgroup'); 
       break; 

      case 'tablerow': 
       exchange('tr'); 
       break; 

      case 'tablesection': 
       exchange('tfoot'); 
       exchange('thead'); 
       exchange('tbody'); 
       break; 

      case 'ulist': 
       exchange('ul'); 
       break; 

      default: 
       console.log('disagree', tagName); 
       if(console.warn && tagName != "") { console.warn("unknown tag name for " + item.constructorName); } 
       break; 
     } 
    }); 

    return items.map(item => item.tagName); 
} 

zmienił 2:

let tagNames = 
[ 
    { name: "a", constr: "HTMLAnchorElement" }, 
    { name: "area", constr: "HTMLAreaElement" }, 
    { name: "audio", constr: "HTMLAudioElement" }, 
    { name: "base", constr: "HTMLBaseElement" }, 
    { name: "body", constr: "HTMLBodyElement" }, 
    { name: "br", constr: "HTMLBRElement" }, 
    { name: "button", constr: "HTMLButtonElement" }, 
    { name: "canvas", constr: "HTMLCanvasElement" }, 
    { name: "content", constr: "HTMLContentElement" }, 
    { name: "data", constr: "HTMLDataElement" }, 
    { name: "datalist", constr: "HTMLDataListElement" }, 
    { name: "details", constr: "HTMLDetailsElement" }, 
    { name: "dialog", constr: "HTMLDialogElement" }, 
    { name: "dir", constr: "HTMLDirectoryElement" }, 
    { name: "div", constr: "HTMLDivElement" }, 
    { name: "dl", constr: "HTMLDListElement" }, 
    { name: "embed", constr: "HTMLEmbedElement" }, 
    { name: "fieldset", constr: "HTMLFieldSetElement" }, 
    { name: "font", constr: "HTMLFontElement" }, 
    { name: "form", constr: "HTMLFormElement" }, 
    { name: "frame", constr: "HTMLFrameElement" }, 
    { name: "frameset", constr: "HTMLFrameSetElement" }, 
    { name: "head", constr: "HTMLHeadElement" }, 
    { name: "h1", constr: "HTMLHeadingElement" }, 
    { name: "h2", constr: "HTMLHeadingElement" }, 
    { name: "h3", constr: "HTMLHeadingElement" }, 
    { name: "h4", constr: "HTMLHeadingElement" }, 
    { name: "h5", constr: "HTMLHeadingElement" }, 
    { name: "h6", constr: "HTMLHeadingElement" }, 
    { name: "hr", constr: "HTMLHRElement" }, 
    { name: "html", constr: "HTMLHtmlElement" }, 
    { name: "iframe", constr: "HTMLIFrameElement" }, 
    { name: "img", constr: "HTMLImageElement" }, 
    { name: "input", constr: "HTMLInputElement" }, 
    { name: "label", constr: "HTMLLabelElement" }, 
    { name: "legend", constr: "HTMLLegendElement" }, 
    { name: "li", constr: "HTMLLIElement" }, 
    { name: "link", constr: "HTMLLinkElement" }, 
    { name: "map", constr: "HTMLMapElement" }, 
    { name: "marquee", constr: "HTMLMarqueeElement" }, 
    { name: "menu", constr: "HTMLMenuElement" }, 
    { name: "meta", constr: "HTMLMetaElement" }, 
    { name: "meter", constr: "HTMLMeterElement" }, 
    { name: "del", constr: "HTMLModElement" }, 
    { name: "ins", constr: "HTMLModElement" }, 
    { name: "object", constr: "HTMLObjectElement" }, 
    { name: "ol", constr: "HTMLOListElement" }, 
    { name: "optgroup", constr: "HTMLOptGroupElement" }, 
    { name: "option", constr: "HTMLOptionElement" }, 
    { name: "output", constr: "HTMLOutputElement" }, 
    { name: "p", constr: "HTMLParagraphElement" }, 
    { name: "param", constr: "HTMLParamElement" }, 
    { name: "picture", constr: "HTMLPictureElement" }, 
    { name: "pre", constr: "HTMLPreElement" }, 
    { name: "progress", constr: "HTMLProgressElement" }, 
    { name: "q", constr: "HTMLQuoteElement" }, 
    { name: "script", constr: "HTMLScriptElement" }, 
    { name: "select", constr: "HTMLSelectElement" }, 
    { name: "shadow", constr: "HTMLShadowElement" }, 
    { name: "slot", constr: "HTMLSlotElement" }, 
    { name: "source", constr: "HTMLSourceElement" }, 
    { name: "span", constr: "HTMLSpanElement" }, 
    { name: "style", constr: "HTMLStyleElement" }, 
    { name: "td", constr: "HTMLTableCellElement" }, 
    { name: "th", constr: "HTMLTableCellElement" }, 
    { name: "col", constr: "HTMLTableColElement" }, 
    { name: "colgroup", constr: "HTMLTableColElement" }, 
    { name: "table", constr: "HTMLTableElement" }, 
    { name: "tr", constr: "HTMLTableRowElement" }, 
    { name: "tbody", constr: "HTMLTableSectionElement" }, 
    { name: "tfoot", constr: "HTMLTableSectionElement" }, 
    { name: "thead", constr: "HTMLTableSectionElement" }, 
    { name: "template", constr: "HTMLTemplateElement" }, 
    { name: "time", constr: "HTMLTimeElement" }, 
    { name: "title", constr: "HTMLTitleElement" }, 
    { name: "track", constr: "HTMLTrackElement" }, 
    { name: "ul", constr: "HTMLUListElement" }, 
    { name: "video", constr: "HTMLVideoElement" } 
]; 
Powiązane problemy