Найти текст между двумя тегами/узлами
Я думал, что это будет довольно просто, но я думаю, что ключевые слова просто слишком общие, поэтому я продолжаю получать результаты запроса для таких вещей, как 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>
Я хотел бы объединить соседние теги 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
Учитывая два тега, как я могу найти текст между ними?
Ответы
Ответ 1
Сбрасывание вниз в DOM позволяет просматривать содержимое node при проверке родных братьев.
Что-то вроде:
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 в этом CodePen.
Ответ 2
Ну, вы можете попробовать это...
По крайней мере, он отлично работает при использовании 2 spans
, чтобы объединить их, как ваш пример (когда присутствует "пустой" элемент). В противном случае вам придется немного подумать о том, чтобы обрабатывать span
, который длится.
(Чтобы проверить, что я говорю, просто взгляните на последнюю строку: nextElem.remove()
и проверьте новый div
html).
Live Demo: 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>
Ответ 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 textNodes=$('#test').contents().filter(function(){
return this.nodeType == 3; // text node
});
Также можно вручную проверять последовательные интервалы, у которых нет пустого текста node между ними, сравнивая каждый 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.
Ответ 5
Хех., похоже, что Оскар Джара и я придумали подобные идеи вокруг использования метода 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 (три пролета спина к спине, пробелы между пробелами между ними и т.д.), все они основаны на вашем исходном коде и, похоже, работают., ключ должен был пропускать любые текстовые узлы "только пробелы" между тегами <span>
, сохраняя при этом все необходимые интервалы, которые они могли содержать.
Ответ 6
Для вашего последнего вопроса "Учитывая два тега, как я могу найти текст между ними?"
Хорошо, у меня есть это решение для вас.
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) concat em в переменной, добавляющей пробелы между ними. Затем выполните эхо-результат, а в функции обратного вызова добавьте его в div
Эта ссылка может помочь вам в том, как сделать POST-вызов в jquery jquery post