【问题标题】:Test if an element can contain text测试元素是否可以包含文本
【发布时间】:2013-11-16 09:54:22
【问题描述】:

如果一个 HTML 元素可以包含一些文本,我是否可以测试(使用纯 javascript 或 jQuery)一种干净而可靠的方法?

例如,<br><hr><tr> 不能包含文本节点,而 <div><td><span> 可以。

测试此属性的最简单方法是控制标签名称。但这是最好的解决方案吗?我认为这是最糟糕的之一......

编辑:为了澄清问题的意义,需要指出完美的答案应该考虑两个问题:

  1. 根据 HTML 标准,元素可以包含文本节点吗?
  2. 如果元素包含一些文本,是否会显示?

显然,上一个列表的每个点都有一个子答案。

【问题讨论】:

  • 加一些文字,看看有没有加,然后去掉?丑,但我不认为有任何其他方式
  • 嗯,问题是技术上<tr> 可以包含文本,它只是呈现在表格上方。
  • 黑名单标签名称可能是唯一可靠的选择...
  • 也许您最好在数组中创建自己的“可文本”标签白名单。
  • 检查节点名称可能是最好的解决方案var node = $('#test')[0].nodeName; node.match(/br|hr|tr/gi);

标签: javascript jquery html dom


【解决方案1】:

我相信你正在寻找void HTML tags的列表:

以下是 HTML 中 void 元素的完整列表:

area、base、br、col、command、embed、hr、img、input、keygen、link、meta、param、source、track、wbr

从那里您只需测试节点以查看它是否在列表中。例如:

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

http://jsfiddle.net/3uQjH/

【讨论】:

  • 非常简单、干净且有效的解决方案。但我还需要一个解决方案,该解决方案还考虑所有不应包含文本的“非空”元素。你有什么想法吗?
  • @VitoShadow 如果您想将更多元素列入黑名单,请将它们的标签添加到数组中。
  • 请注意,数组上的indexOf 最初是在 IE9 中添加的。
【解决方案2】:

The W3 standard for "void elements" 指定:

虚空元素
area, base, br, col, embed, hr, img, input, keygen, link, menuitem, meta, param, source, track, wbr

显然还有一些unofficial 标签。

可以建立黑名单,使用.prop('tagName')获取标签名:

(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

在这里,您还可以将自己的标签添加到cannotContainText(例如添加&lt;tr&gt;,它不是正式的 void 元素,因为它与 specification 不匹配“一个 void 元素是一个元素其内容模型在任何情况下都不允许它有内容。void 元素可以有属性。")。

【讨论】:

  • 这是一个非常好的答案。但是您是否知道某种方式(或类似上述的官方列表)来考虑所有不应包含文本的“非空”元素?
  • @VitoShadow 我不确定,但在w3 page 上,您可以看到允许使用哪些元素。如果允许“流内容”,则它允许文本。您可能想在 w3 中抓取没有“流控制”的元素,但到目前为止我不知道任何其他方法。 tr, for example, doesn't have flow content.
  • 非常有趣。现在我们只需要一个方法来测试一个元素是否可以有流内容:)
【解决方案3】:

我基本上同意每个人的观点,黑名单将是一种非常正统的做法,但如果我们真的需要测试能力,那么这将是我认为的一种方式(使用一些 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;}
}

我在 Chrome 上对各种标签名称进行了测试,得到了以下结果:

    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

我们也可以在这两个例子中使用 jquery "prop" 测试一些真实的标签:

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

这给出了:

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

虽然我确信它远非完美,但研究起来很有趣。

【讨论】:

  • 我在 Firefox 24 中测试了您的解决方案,但它不起作用...它总是返回 true。我认为问题在于$('&lt;'+tagName+'&gt;&lt;/'+tagName+'&gt;') 没有创建渲染节点……有可能吗?
  • 根据标准trtbody 也不能包含文本,所以虽然这个应该给出比黑名单更准确的表示,但它似乎仍然失败特定时间。
猜你喜欢
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
相关资源
最近更新 更多