2013-07-15 2 views
12

Я думал, что это будет довольно просто, но я думаю, что ключевые слова просто слишком общие, поэтому я продолжаю получать результаты запроса для таких вещей, как this и this.Найти текст между двумя тегами/узлами

В принципе, у меня есть следующий 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> 

Я хотел бы объединить соседние теги пролетных в один тег диапазона, что означает нахождение пролеты с единственным пробелом между ними (это может включать пробелы, вкладки и новые строки).

В результате я ищу это:

<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 сидят Амет, consecteturadipiscing

Учитывая два тега, как я могу найти текст между их?

+0

Вы хотите найти текст между тегами или Concat их? –

+0

@OscarJara: Он хочет конкатенировать теги * если * текст между ними - пробел. –

+0

Возможно ли, чтобы у двух пролетов не было пробела, табуляции или новой строки между ними, или у них всегда будет только один из них? – j08691

ответ

5

Сбрасывание до 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(); 
    } 
} 

Используя это с HTML в this CodePen.

+0

Я не эксперт по jQuery, поэтому чтение между строками здесь звучит так, как будто jQuery плохо подходит для извлечения текста, который * не * содержится в теге. – JDB

+0

Это следующие/предыдущие методы - нет, нет. –

+0

Принимается, потому что он работает с более чем двумя «смежными» пролетами. – JDB

-1

Для вашего последнего вопроса «Учитывая два тега, как я могу найти текст между ними?»

Ну, у меня есть это решение для вас.

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" 

и для каждого матча (с начала цикла) concat em в переменной, добавляющей пробелы между ними. Затем сделайте отголосок свой результат и в вашей функции обратного вызова добавьте его в DIV

Эта ссылка может помочь вам в том, как сделать вызов POST в JQuery jquery post

+0

Я ценю усилие, но если регулярное выражение является единственным решением, то я не буду продолжать это делать дальше. Я также хочу обрабатывать этот 100% на стороне клиента, поэтому PHP не является решением. – JDB

+3

И pleeeease не анализируют HTML с регулярными выражениями. http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 –

+0

Я уже прочитал этот вопрос, и в этом случае не выглядит например, существует проблема с анализом HTML с регулярным выражением. Я считаю, что downvote не нужен – Mollo

0

как запрос в заголовке его, вот возможный способ получить текстовые узлы между пролетами:

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.

1

Ну, вы можете попробовать это ...

По крайней мере, он отлично работает при использовании 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> 
+0

Работает с примером, но вроде разваливается при вводе третьего интервала. Вы уже упомянули эту проблему в своем ответе, так что +1 за усилия. – JDB

+0

@ Cyborgx37 Да, я знаю об этом, поэтому я сказал вам, что вам нужно работать над этим (но кажется простым, просто удалите 'nextElem.remove()' и посмотрите, что это будет работать для большего количества тегов span) зависит от вас, чтобы исправить это, но вы в правильном направлении (я думаю) :-) –

0

Хех. , , выглядит как Оскар Хара, и я пришел с подобными идеями вокруг, используя .contents() метод JQuery, но в конечном итоге с некоторыми существенно различных реализаций:

$(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-данных (три пролеты обратно-to назад, пробелы между пробелами между и без и т. д.), все они основаны на вашем исходном коде и, похоже, работают. , , ключ должен был пропускать любые текстовые узлы «только пробелы» между тегами <span>, сохраняя при этом все необходимые интервалы, которые они могли содержать.

1

Я знаю, что вы уже приняли решение, но я хотел взять на себя задачу предоставить чистое решение для 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'); 
Смежные вопросы