cc young
cc young

Reputation: 20245

how to determine whether string is a valid html4 tagName?

given a string, 'div' or 'abc', is there any way to determine whether the string is a valid html4 tagName?

tried using document.createElement(), but it's happy with anything:

document.createElement('trash')
=> <trash></trash>

cannot use HTML<tag>Element. for example

document.createElement('tbody')
=> HTMLTableSelectorElement

Upvotes: 1

Views: 466

Answers (3)

SpYk3HH
SpYk3HH

Reputation: 22580

Was looking for a solution to this, but a bit more complete. The snippet below is the final result of searching around Stack and Google. It's not quite as simplistic as the HTML4 array check up there, but not much more complicated either.

The method is simple. Call it, pass string as param, will return true if it valid HTML5 tag. So far it's worked on every tag I can think of.

There is a second param, named "allowObsolete". As the name suggest, it will allow for obsolete tags like applet to return true as well, otherwise, obsolete tags automatically return false.

One more thing! Pass -1 as second parameter to completely bypass the obsolete check. The obsolete check is preformed based on an array made from W3C HTML5 Standards of what tags are obsolete as of 28 October 2014.

Little extra. Just added a small bit that will also return false if you try to pass in a CSS selector/Comparison symbol. Basically anything that is not an alphanumeric character will cause it to return false. If you decide to edit, keep in mind, it can't be limited to just alpha as tehre are tags like h1.

Simple snippet

/** isValidHTMLTag(String, Mixed Var)
 * 
 *  @description Simple and effective way of checking whether an string is a valid HTML Tag Name.
 *
 *  @note Not yet tested on all Browsers. Use discreetly.
 *
 *  @example isValidHTMLTag('input');   //  returns `true`
 *  @example isValidHTMLTag('blink');   //  returns `false` because `blink` is obsolete
 *  @example isValidHTMLTag('blink', true); //  returns `true`
 *  @example isValidHTMLTag('blink', -1);   //  returns `false` in an HTML5 browser
 *  
 *  @param {String} tagName *Required | The string to check for validity.
 *  @param {Boolean|Integer} Determine whether or not to allow possible Obsolete Tag Names to return true. Set to `-1` to completely bypass this option. [undefined==false]
 *  @returns {Boolean} `true` if valide, otherwise `false`
 */
function isValidHTMLTag(tagName, allowObsolete) {   //  use `-1` as second parameter to completely bypass allowObsolete check
    var obsolete = ['acronym', 'applet', 'basefont', 'bgsound', 'big', 'blink', 'center', 'dir', 'font', 'frame', 'frameset', 'hgroup', 'isindex', 'listing', 'marquee', 'multicol', 'nextid', 'nobr', 'noembed', 'noframes', 'plaintext', 'spacer', 'strike', 'tt', 'xmp'];
    return tagName.match(/[^a-zA-Z0-9]/) ? !1 : -1 !== allowObsolete && -1 !== obsolete.indexOf(tagName) ? allowObsolete || !1 : "[object HTMLUnknownElement]" !== Object.prototype.toString.call(document.createElement(tagName));
}

One Liner!

function isValidHTMLTag(a,b){var c="acronym applet basefont bgsound big blink center dir font frame frameset hgroup isindex listing marquee multicol nextid nobr noembed noframes plaintext spacer strike tt xmp".split(" ");return a.match(/[^a-zA-Z0-9]/)?!1:-1!==b&&-1!==c.indexOf(a)?b||!1:"[object HTMLUnknownElement]"!==Object.prototype.toString.call(document.createElement(a))};

Naughty Tip Modify the DOM! using below

Object.defineProperty && !Element.prototype.hasOwnProperty("isValidTag") ? Object.defineProperty(Element.prototype, "isValidTag", {
        value: function(b) {
            if (this.tagName) {
                var c = "acronym applet basefont bgsound big blink center dir font frame frameset hgroup isindex listing marquee multicol nextid nobr noembed noframes plaintext spacer strike tt xmp".split(" "),
                    a = this.tagName;
                return a.match(/[^a-zA-Z0-9]/) ? !1 : -1 !== b && -1 !== c.indexOf(a.toLowerCase()) ? b || !1 : "[object HTMLUnknownElement]" !== Object.prototype.toString.call(document.createElement(a))
            }
            return !1
        }
    }) :
    Element.prototype.isValidTag = function(b) {
        if (this.tagName) {
            var c = "acronym applet basefont bgsound big blink center dir font frame frameset hgroup isindex listing marquee multicol nextid nobr noembed noframes plaintext spacer strike tt xmp".split(" "),
                a = this.tagName;
            return a.match(/[^a-zA-Z0-9]/) ? !1 : -1 !== b && -1 !== c.indexOf(a.toLowerCase()) ? b || !1 : "[object HTMLUnknownElement]" !== Object.prototype.toString.call(document.createElement(a))
        }
        return !1
    };

//  Use like:
var blinky = document.createElement('blink');
if (!blinky.isValidTag()) {
    var head = document.head || document.getElementsByTagName("head")[0],
        style = document.createElement("style");
    style.appendChild(document.createTextNode("@keyframes blink { from { opacity: 1; } to { opacity: 0; } }"));
    style.appendChild(document.createTextNode("@-webkit-keyframes blink { from { opacity: 1; } to { opacity: 0; } }"));
    style.appendChild(document.createTextNode("blink { -webkit-animation: blink 600ms infinite; animation: blink 600ms infinite; text-decoration: blink; }"));
    head.appendChild(style);
}

Then you can do something like this snippet!

Object.defineProperty&&!Element.prototype.hasOwnProperty("isValidTag")?Object.defineProperty(Element.prototype,"isValidTag",{value:function(b){if(this.tagName){var c="acronym applet basefont bgsound big blink center dir font frame frameset hgroup isindex listing marquee multicol nextid nobr noembed noframes plaintext spacer strike tt xmp".split(" "),a=this.tagName;return a.match(/[^a-zA-Z0-9]/)?!1:-1!==b&&-1!==c.indexOf(a.toLowerCase())?b||!1:"[object HTMLUnknownElement]"!==Object.prototype.toString.call(document.createElement(a))}return!1}}):
Element.prototype.isValidTag=function(b){if(this.tagName){var c="acronym applet basefont bgsound big blink center dir font frame frameset hgroup isindex listing marquee multicol nextid nobr noembed noframes plaintext spacer strike tt xmp".split(" "),a=this.tagName;return a.match(/[^a-zA-Z0-9]/)?!1:-1!==b&&-1!==c.indexOf(a.toLowerCase())?b||!1:"[object HTMLUnknownElement]"!==Object.prototype.toString.call(document.createElement(a))}return!1};

$('body > *:not(hr)').each(function(i) {
  $(this).find('.tag-name').text(this.tagName);
  $(this).find('.is-not').html('is' + (this.isValidTag(i==5?-1:null) ? '' : ' <b>NOT</b>'));
});
/* Standard (Mozilla) */
@keyframes blink { from { opacity: 1; } to { opacity: 0; } }
/* Chrome & Safari */
@-webkit-keyframes blink { from { opacity: 1; } to { opacity: 0; } }
blink { -webkit-animation: blink 600ms infinite; animation: blink 600ms infinite; text-decoration: blink; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</div>
<hr />
<blink>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</blink>
<hr />
<p>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</p>
<center>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal <sub>but is still supported in most browsers. Thus use the bypass param "-1"</sub></center>
<hr />
<center>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</center>
<hr />
<article>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</article>
<hr />
<header>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</header>
<hr />
<a href="javascript:void 0">Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</a>
<hr />
<penguin>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</penguin>
<hr />
<pre>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</pre>
<hr />
<footer>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</footer>
<hr />
<bob>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</bob>
<hr />
<h9>Tag Name [<b><span class="tag-name"></span></b>] [<i><span class="is-not"></span></i>] legal</h9>

Upvotes: 1

Ry-
Ry-

Reputation: 225164

The best way is to have a list of all valid HTML4 elements and check that. This will give you the right result for "a valid HTML4 element" 100% of the time. From here:

var html4 = ["A","ABBR","ACRONYM","ADDRESS","APPLET","AREA","B","BASE","BASEFONT","BDO","BIG","BLOCKQUOTE","BODY","BR","BUTTON","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","DD","DEL","DFN","DIR","DIV","DL","DT","EM","FIELDSET","FONT","FORM","FRAME","FRAMESET","H1","H2","H3","H4","H5","H6","HEAD","HR","HTML","I","IFRAME","IMG","INPUT","INS","ISINDEX","KBD","LABEL","LEGEND","LI","LINK","MAP","MENU","META","NOFRAMES","NOSCRIPT","OBJECT","OL","OPTGROUP","OPTION","P","PARAM","PRE","Q","S","SAMP","SCRIPT","SELECT","SMALL","SPAN","STRIKE","STRONG","STYLE","SUB","SUP","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TITLE","TR","TT","U","UL","VAR"];

var valid = html4.indexOf(name.toUpperCase()) !== -1;

If you absolutely don't want to do that for some reason, or didn't actually mean HTML4, and aren't worried about IE8- compatibility, then you can do this:

var valid = !(document.createElement(name) instanceof HTMLUnknownElement);

Upvotes: 6

Starx
Starx

Reputation: 79041

A rather simple technique is to define your own set of valid HTML Elements

Array.prototype.contains = function(k) {
   return (this.indexOf(k) > -1;
}
var ValidTags = ['html', 'head', ....];
//Then compare
if(ValidTags.contains('trash')) {
   //Then its valid
}

Upvotes: 0

Related Questions