最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Test if an element can contain text - Stack Overflow

programmeradmin1浏览0评论

Is there a clean and robust way in which I can test (using pure javascript or also jQuery) if an HTML element can contain some text?

For instance, <br>, <hr> or <tr> cannot contain text nodes, while <div>, <td> or <span> can.

The simplest way to test this property is to control the tag names. But is this the best solution? I think it is one of the worst...

EDIT: In order to clarify the sense of the question, need to point out that the perfect answer should consider two problems:

  1. According to HTML standards, can the element contain a text node?
  2. If the element contains some text, will it be shown?

Obviously, there is a sub-answer for each point of the previous list.

Is there a clean and robust way in which I can test (using pure javascript or also jQuery) if an HTML element can contain some text?

For instance, <br>, <hr> or <tr> cannot contain text nodes, while <div>, <td> or <span> can.

The simplest way to test this property is to control the tag names. But is this the best solution? I think it is one of the worst...

EDIT: In order to clarify the sense of the question, need to point out that the perfect answer should consider two problems:

  1. According to HTML standards, can the element contain a text node?
  2. If the element contains some text, will it be shown?

Obviously, there is a sub-answer for each point of the previous list.

Share Improve this question edited Sep 7, 2021 at 14:42 Vito Gentile asked Nov 5, 2013 at 13:44 Vito GentileVito Gentile 14.5k11 gold badges64 silver badges97 bronze badges 10
  • add some text, see if it added, then remove it? ugly but i don't think there's any other way – jbabey Commented Nov 5, 2013 at 13:46
  • 1 Well, the problem is that technically <tr> can contain text, it just gets rendered above the table. – Niet the Dark Absol Commented Nov 5, 2013 at 13:47
  • 3 Blacklisting tag names may be the only reliable option... – Niet the Dark Absol Commented Nov 5, 2013 at 13:47
  • 2 Maybe you'd be better off just created your own whitelist of 'text-able' tags in an array. – George Commented Nov 5, 2013 at 13:48
  • 1 checking node name is probably the best solution var node = $('#test')[0].nodeName; node.match(/br|hr|tr/gi); – Anton Commented Nov 5, 2013 at 13:49
 |  Show 5 more ments

3 Answers 3

Reset to default 5

The W3 standard for "void elements" specifies:

Void elements
area, base, br, col, embed, hr, img, input, keygen, link, menuitem, meta, param, source, track, wbr

And apparently there's some unofficial tags as well.

You can make a black list and use .prop('tagName') to get the tag name:

(function ($) {
    var cannotContainText = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX'];

    $.fn.canContainText = function() {
        var tagName = $(this).prop('tagName').toUpperCase();

        return ($.inArray(tagName, cannotContainText) == -1);
    };
}(jQuery));

$('<br>').canContainText(); //false
$('<div>').canContainText(); //true

Here you can also add your own tags to cannotContainText (eg. to add <tr> which is not officially a void element as it doesn't match the specification "A void element is an element whose content model never allows it to have contents under any circumstances. Void elements can have attributes.").

I believe you're looking for a list of void HTML tags:

The following is a plete list of the void elements in HTML:

area, base, br, col, mand, embed, hr, img, input, keygen, link, meta, param, source, track, wbr

From there you would just test the node to see if it is in the list. For example:

var voidNodeTags = ['AREA', 'BASE', ...];
var isNodeVoid = function (node) {
    return voidNodeTags.indexOf(node.nodeName) !== -1;
};

http://jsfiddle/3uQjH/

I mostly agree with everybody that a blacklist would be a very orthodox way of doing it but if we are really required to test for the ability, then this would be one way I think (with some jquery):

isTextContainerTag=function(tagName){
    try{       
        var test = $('<'+tagName+'></'+tagName+'>');
        test.html(123);
        if(test.html()=='123'){
            return true;   
        }else{
            return false;   
        }
    }
    catch(err){return false;}
}

I tested it on Chrome on various tags names and got these results:

    console.log('input',isTextContainerTag('input'));//answer:false
    console.log('textarea',isTextContainerTag('textarea'));//true
    console.log('option',isTextContainerTag('option'));//true
    console.log('ul',isTextContainerTag('ul'));//true
    console.log('li',isTextContainerTag('li'));//true
    console.log('tr',isTextContainerTag('tr'));//true
    console.log('td',isTextContainerTag('td'));//true
    console.log('hr',isTextContainerTag('hr'));//false
    console.log('br',isTextContainerTag('br'));//false
    console.log('div',isTextContainerTag('div'));//true
    console.log('p',isTextContainerTag('p'));//true
    console.log('html',isTextContainerTag('html'));//false
    console.log('body',isTextContainerTag('body'));//false
    console.log('table',isTextContainerTag('table'));//false
    console.log('tbody',isTextContainerTag('tbody'));//true

We may also test some real tags using jquery "prop" on these two examples:

<div id="A">AAAAAA</div>
<br id="B">

Which gives:

var obj1 = $('#A').prop('tagName');
var obj2 = $('#B').prop('tagName');
console.log('id:A (div)',isTextContainerTag(obj1));//true
console.log('id:B (br)',isTextContainerTag(obj2));//false

I'm sure it is way away from perfect though, but it was fun to look into.

发布评论

评论列表(0)

  1. 暂无评论