All HTML Tags supported by a Browser

后端 未结 4 1171
心在旅途
心在旅途 2020-12-11 02:23

Using JavaScript, is it possible to obtain a list of the tags that a browser supports?

相关标签:
4条回答
  • 2020-12-11 03:06

    Every JavaScript html element object, created by document.createElement(), has a constructor function which always starts with "HTML..." and ends with "...Element". All these are inherit from HTMLElement. Each of these are reachable in the window object via Object.getOwnPropertyNames().

    So you can get all valid tag names by iterate over all property names in window and filter them with 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;
    }
    

    How to use it:

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

    edit

    Some constructor functions for html elements are just base constructor functions (for example HTMLMediaElement). In this case the base constructor function of HTMLAudioElement (<audio></audio>) and HTMLVideoElement (<video></video>) are not directly inherit from HTMLElement. So it's necessary to run through the complete protype chain, the instanceof operator is suitable for this:

    window['HTMLAudioElement'].prototype instanceof HTMLElement
    

    Another aspect is that some constructor function names fit not to the equivalent html tag name (<a> => HTMLAnchorElement) and some other names fit to several tags (for example <h1></h1>, <h2></h2>, <h3></h3>, <h4></h4>, <h5></h5>, <h6></h6>) with the same constructor function. > see mdn.

    Currently there is no other way in JavScript to create the wrong identified tag name with document.createElement(tagName);, check whether the constructor is an HTMLUnknownElement and fixed these manually:

    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);
    }
    

    edit 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" }
    ];
    
    0 讨论(0)
  • 2020-12-11 03:15

    You can get a decent idea of what is supported by introspection on the window.

    Try this out:

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

    This is in no way exhaustive as far as I know but it will tell you in most browsers what tags have a DOM object type.

    Here is sample output by running this in my Chrome console:

    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
    
    0 讨论(0)
  • 2020-12-11 03:20

    If you're willing to start with a known list of candidate tags, you could try something like this:

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

    If you need to support IE8, you could use this approach:

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

    Here's another approach that doesn't rely on specific named constructors.

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

    It still doesn't seem to work in IE8 though.

    0 讨论(0)
  • 2020-12-11 03:21

    There is no general way but each element has specific way to see if it's supported

    Canvas element support:

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

    Input type support:

    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
    

    Audio element support:

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

    Progress element support

    var progressElementSupported = "max" in document.createElement("progress");
    
    0 讨论(0)
提交回复
热议问题