【问题标题】:Find text between two tags/nodes在两个标签/节点之间查找文本
【发布时间】:2013-07-17 05:55:54
【问题描述】:

我认为这会很简单,但我认为关键字太笼统了,所以我不断获得诸如 thisthis 之类的查询结果。

基本上,我有以下 HTML:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur</span>
    <span class="highlighted">adipiscing</span>
    elit. Sed massa.
<div>

我想将相邻的 span 标签合并为一个 span 标签,这意味着查找它们之间只有空格的 span(这可能包括空格、制表符和换行符)。

我要找的结果是这样的:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur adipiscing</span>
    elit. Sed massa.
<div>

我检查了nextUntil 函数,但它似乎只返回标签,而不是文本。结果,例如,

$("span.highlighted").nextUntil("span.highlighted").andSelf().text();

ipsumconsecteturadipiscing

而不是

ipsum dolor sit amet, consecteturadipiscing

给定两个标签,我怎样才能找到它们之间的文本

【问题讨论】:

  • 您要查找标签之间的文本还是将它们连接起来?
  • @OscarJara:他想连接标签如果它们之间的文本是空格。
  • 两个跨度之间是否有可能没有空格、制表符或换行符,或者它们总是只有其中一个?
  • 我也想知道 OP 是否会处理超过 2 个或 3 个标签
  • @j08691 - 如果您查看我的示例,您将看到 3 个跨度标签。其中一个由非空格分隔,其中两个仅由空格分隔。当且仅当标签之间仅包含空格时,我想将它们合并在一起。

标签: javascript jquery dom


【解决方案1】:

下拉到 DOM 让您在检查同级时查看文本节点内容。

类似:

function combineSpans(span, nextspan)
{
  var follower = span.nextSibling;
  var concat = true;

   while (follower != nextspan)
   {
     if (follower.nodeName != '#text')
     {
       concat = false;
       break;
     }

     var len = follower.data.trim().length;
     if (len > 0)
     {
       concat = false;
       break;
     }

     follower = follower.nextSibling;
   }

  if (concat)
  {
    $(span).text($(span).text() + " " + $(follower).text());
    $(follower).remove();
  }
}

this CodePen 中将其与您的 HTML 一起使用。

【讨论】:

  • 我不是 jQuery 专家,所以从字里行间看,jQuery 不太适合提取 not 包含在标签中的文本。
  • 它的下一个/上一个方法不是,不。
  • 接受,因为它适用于两个以上的“相邻”跨度。
【解决方案2】:

嗯,你可以试试这个……

至少在使用 2 spans 像您的示例一样合并它们时它可以完美运行(当存在“空”元素时)。否则,您需要花点心思来处理持续存在的span

(要检查我在说什么,只需看看评论最后一行:nextElem.remove() 并检查新的div html)

现场演示: http://jsfiddle.net/oscarj24/t45MR/


HTML:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur</span>
    <span class="highlighted">adipiscing</span>
    elit. Sed massa.
</div>

jQuery:

$(document).ready(function () {

    var elem = $('#test');

    elem.contents().filter(function(index) {
        //Get index of an empty element
        if($.trim($(this).text()) === '') 
            //Merge the previous index span with the next index span texts
            mergeSpan(index);
    });

    //Print new inner html
    alert(elem.html());
});

function mergeSpan(index){

    //Get all 'div' elements
    var elems = $('#test').contents();

    //Get previous and next element according to index
    var prevElem = elems.eq(index - 1);
    var nextElem = elems.eq(index + 1);

    //Concat both texts
    var concatText = prevElem.text() + ' ' + nextElem.text();

    //Set the new text in the first span
    prevElem.text(concatText);
    //Remove other span that lasts
    nextElem.remove();
};

结果:

<div id="test">
    Lorem
    <span class="highlighted">ipsum</span>
    dolor sit amet,
    <span class="highlighted">consectetur adipiscing</span>
    elit. Sed massa.
<div>

【讨论】:

  • 适用于该示例,但在引入第三个跨度时有点崩溃。您已经在回答中提到了这个问题,所以 +1 的努力。
  • @Cyborgx37 是的,我知道,这就是为什么我告诉你你需要解决这个问题(但看起来很简单,只需删除 nextElem.remove() 并看看这将适用于更多 span标签)只取决于你修复它,但你的方式是正确的(我认为):-)
【解决方案3】:

我知道您已经接受了一个解决方案,但我想接受挑战,提供一个可以整合到您的工具集中的纯 JavaScript 解决方案。这是我想出的,希望得到任何帮助以使其变得更好。

http://jsfiddle.net/ryanwheale/JhZPK/

function joinNeighborsByClassName( className ) {
    var items = document.getElementsByClassName(className),
        next = null,
        remove = [],
        append = '',
        i = 0;

    while( i < items.length && (next = items[i++]) ) {
        while( (next = next.nextSibling) && next !== null ) {
            if((next.nodeType === 3  && /^\s+$/.test(next.nodeValue)) ||     
               (new RegExp("(?:^|\s)" + className + "(?!\S)", "g")).test(next.className) ) {
                append += (next.innerHTML || next.nodeValue);

                if(next.nodeType !== 3) {
                    remove.push(next);
                }
            } else {
                break;
            }
        }

        if(append) items[i-1].innerHTML += append;
        for(var n = 0; n < remove.length; n++) {
            remove[n].parentNode.removeChild(remove[n]);
        }

        remove = [];
        append = '';
    }
}

joinNeighborsByClassName('highlighted');

【讨论】:

    【解决方案4】:

    对于您的最后一个问题“给定两个标签,我如何找到它们之间的文本?”

    嗯,我有这个解决方案给你。

    var divData = $("#test").html(); // Getting html code inside div
    

    现在,使用 preg_match() 您可以获得两个单词之间的文本,在您的情况下是跨度之间的文本,如下所示:

    preg_match('/'.preg_quote($word1).'(.*?)'.preg_quote($word2).'/is', $html, $matches);
    
    $word1 = '<span class="highlighted">';
    $word2 = '<';
    $html = $_POST['divData']; // Via post/get you will have to send the html code gotten in "var divData"
    

    并且对于每个匹配项(带有 for 循环)在变量中连接 em,在它们之间添加空格。然后回显您的结果并在您的回调函数中将其添加到您的 div 中

    此链接可以帮助您了解如何在 jquery jquery post 中进行 POST 调用

    【讨论】:

    • 我很感激你的努力,但如果正则表达式是唯一的解决方案,那么我不会再继续这样做了。我也想在客户端处理这个 100%,所以 PHP 不是一个解决方案。
    • 请不要使用正则表达式解析 HTML。 stackoverflow.com/questions/1732348/…
    • 我已经阅读了这个问题,在这种情况下,使用正则表达式解析 HTML 似乎没有问题。我认为没有必要投反对票
    • 我同意@PaulRoub 的观点,即用正则表达式匹配 HTML 是个坏主意。请让 DOM 决定它是否是一个有效的节点。
    【解决方案5】:

    根据标题的要求,这里有一种在跨度之间获取文本节点的可能方法:

    var textNodes=$('#test').contents().filter(function(){
        return this.nodeType == 3; // text node
    });
    

    还可以通过将每个节点与前一个节点进行比较来手动检查它们之间没有空文本节点的连续跨度。像这样的东西可以解决问题:

    function combineSpansIn(selector, spanClass) {
        // initialize precedent values
        var prec=null;
        var precNodeType;
    
        $(selector).contents().each(function(){
            if ($.trim( $(this).text() ) !== "") { // empty nodes will be useless here
                var nodeType = this.nodeType;
    
                // check if still a combinable span
                if (nodeType == 1 && this.className==spanClass && nodeType == precNodeType) {
                    // append current node to precedent one
                    $(prec).append(" "+ $(this).text() );
    
                    // remove current node
                    $(this).remove();
                } else {
                    // update precedent values
                    prec=this;
                    precNodeType = nodeType;
                }
            }
        });
    }
    
    combineSpansIn('#test', 'highlighted');
    

    请看一下这个FIDDLE

    【讨论】:

      【解决方案6】:

      嘿嘿。 . .看起来 Oscar Jara 和我在使用 JQuery .contents() 方法时提出了类似的想法,但最终得到了一些截然不同的实现:

      $(document).ready(function () {
          $("#testDiv").contents().each(function() {
              var prevNode = this.previousSibling;
              var fillerText = "";
              while ((prevNode) && ($.trim($(prevNode).text()) === "")) {
                  fillerText += prevNode.nodeValue;
                  prevNode = prevNode.previousSibling;
              }
      
              if ((prevNode) && (this.nodeType === 1) && (prevNode.nodeType === 1)) {
                  $(prevNode).text($(prevNode).text() + fillerText + $(this).text());
                  $(this).remove();
              }
          });
      });
      

      我根据您的原始代码测试了几组不同的 HTML 数据(三个连续的跨度、中间和没有空格的跨度等),它似乎有效。 . .关键是要跳过&lt;span&gt; 标签之间的任何“仅空白”文本节点,同时保留它们可能包含的任何所需间距。

      【讨论】:

        猜你喜欢
        • 2019-10-31
        • 2023-01-01
        • 2014-08-03
        • 2023-03-19
        • 2017-12-25
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多