4

我想“管理” div 中的第一个 h2 元素,前提是它真的是“第一个元素”

<div id="test">
    <h2>Try 1</h2>
    Test Test Test
    <h2>Try 2</h2>
</div>  

这里只有带有文本“Try 1”的 h2 必须被管理

<div id="test">
    Test Test Test
    <h2>Try 1</h2>
    <h2>Try 2</h2>
</div>  

这里没有(之前有文字)。

我怎么能用 jQuery 做到这一点?

4

6 回答 6

4

不需要jquery,只需:

document.getElementById('test').firstChild.nodeName // gives the name of the node

这将为您提供第一个节点的名称,即使它不是标签而只是纯文本节点!

document.querySelector()如果您想更灵活地使用选择器并且知道大多数客户端浏览器都支持它,您当然可以选择使用它。

需要明确的是:如果您添加换行符,这也将被视为文本节点,因此标题需要从同一行开始,否则您将得到#text两个示例的结果!

这将失败:

<div id="test">
    <h2>Try 1</h2>
    Test Test Test
    <h2>Try 2</h2>
</div>

这将起作用:

<div id="test"><h2>Try 1</h2>
    Test Test Test
    <h2>Try 2</h2>
</div>

给你一个小演示

于 2012-12-14T14:12:00.303 回答
2

我们在这里面临的挑战是 javascript 也将空格识别为文本节点。因此,从 javascript 的角度来看,这个 HTML:

<div id="test">
    <h2>Try 1</h2>    
    Test Test Test    
    <h2>Try 2</h2>
</div>

与此 HTML 不同:

<div id="test"><h2>Try 1</h2>    
    Test Test Test    
    <h2>Try 2</h2>
</div>

在第一种情况下, 中的第一个节点div是 textNode ( nodeType == 3) 在第二个 HTML 示例中, 中的第一个节点divh2节点。

我为此想出了一个解决方案,这是一个方便的函数,它遍历结合了 jQuery 和本机 javascript 的所有元素。

解决方案

var objNodes = $(".wrapper").contents().get();

  function loopNodes(objNodes, i) {
    i = (typeof i === "undefined") ? 0 : i;

    if (objNodes[i].nodeType !== 3) {
      return {"isHeader":true, "first":$(objNodes[i])};

    } else {
      var strText = objNodes[i].innerText || objNodes[i].textContent;
      if ($.trim(strText).length === 0) {
        return loopNodes(objNodes, i+1);

      } else {
        return {"isHeader":false, "first":null};

      }
    }
  }

用法

var objResults = loopNodes(objNodes);
if (objResults.isHeader) {
    console.log("Coolness");
    objResults.first.text("AWESOME FIRST HEADER!"); 
} else {
    console.log("Less Coolness");
}

在行动:http: //jsbin.com/welcome/61883/edit

编辑:添加了获取 innerText/textContent 的跨浏览器方式。有关此事的完整参考资料,请参阅Quirksmode

于 2012-12-14T14:18:48.047 回答
2

我想我找到了一个解决方案,有点好笑:

if($.trim($('#test').html()).substr(0,4).toLowerCase() == "<h2>")
{
    $('#test h2:first').css('background-color', 'red');
}

你有什么想法?:)

于 2012-12-14T14:40:26.580 回答
2

您可以使用.contents有条件地忽略仅是空白文本的前导节点。然后查看第一个节点是否为<h2>Fiddle):

function isFirstChildH2(selector) {
    // get th efirst node, which may be a text node
    var firstNode = $(selector).contents().first();

    // if the first node is all whitespace text, ignore it and go to the next
    if(firstNode[0].nodeType == 3 && firstNode.text().match(/\S/g) == null) {
        firstNode = firstNode.next();
    }

    if(firstNode.is("h2")) {
        // it's an h2; do your magic!
        alert("h2 is the first thing on " + selector)
     } else {
        // first node is either non-whitespace text or an non-h2 element
        // don't do your magic
        alert("h2 is NOT the first thing on " + selector)
     }
}

isFirstElementH2("#test");
于 2012-12-14T14:44:49.253 回答
2

这是您将如何过滤以仅获取第一个节点的标题,忽略所有空白文本节点:-

$("#test").children("h2").first().filter(function() {

    var childNodes = this.parentNode.childNodes;
    var i = 0;
    var textNode = 3;

    // No children
    if(!childNodes.length) {
        return false;
    }

    // Skip blank text node
    if(childNodes[i].nodeType === textNode && childNodes[i].textContent.trim().length === 0) {
        i ++;
    }

    // Check we have a match
    return childNodes[i] === this;

});

这是在行动http://jsfiddle.net/nmeXw/

于 2012-12-14T14:54:25.587 回答
1

好的,让我们将一些 jQuery 与纯 DOM 代码混合(因为 jQuery 无法处理文本节点):

var $el = $("#test > h2:first-child");
if (!$el.length) return false;
var el = $el.get(0),
    reg = /\S/; // no whitespace
for (var prev = el; prev = prev.previousSibling; )
    if (prev.nodeType == 3 && reg.test(prev.data))
        return false;
return el;

jsfiddle.net 上的演示

于 2012-12-14T14:26:39.093 回答