How can I select an element and the text that follows it with jQuery?

Viewed 24

I'm trying to find a class within a sentence and wrap it along with remainder of the text in the sentence.

What I want:

<div class="container">
  text text text text text text text text text text text text text text text 
  text text text text text text text text <div class="newWrap"><div class="test">TEST</div> text
  text text text text text text text text text text text text text text text</div>
</div>

One of the many efforts I've tried:

$('.test').each(function() {
  $(this).nextUntil('div').addBack().wrap('<div class="newWrap"></div>');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="containter">
    text text text text text text text text text text text text text text text 
    text text text text text text text text <div class="test">TEST</div> text
    text text text text text text text text text text text text text text text
</div>

2 Answers

Get next sibling Node

No need to use jQuery. in pure JavaScript:

// DOM Utility functions:

const EL = (sel, par) => (par || document).querySelector(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

// Task:

const EL_test = EL(".test");
const ND_next = EL_test.nextSibling;
const EL_newWrap = ELNew("div", {className: "newWrap"});

EL_newWrap.append(EL_test, ND_next);
EL(".containter").append(EL_newWrap);
div { padding: 10px; outline: 1px solid red; }
.newWrap { background: gold; }
<div class="containter">
  aaaa aaaa aaaa aaaa aaaa aaaa
  <div class="test">TEST</div>
  bbbb bbbb bbbb bbbb bbbb bbbb
</div>

Notice:

As per requirement the above will only target the first Node sibling, so if you have other elements like <br> etc, it will not work as expected. So read furhther.

Get all next sibling Nodes

A while loop would be necessary in order to reach the end of the parent container and get all the next siblings.
In such case the target .test element should be prepended last (after the while loop):

// DOM Utility functions:

const EL = (sel, par) => (par || document).querySelector(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

// Task:

const EL_test = EL(".test");
const EL_newWrap = ELNew("div", {className: "newWrap"});

while(EL_test.nextSibling) EL_newWrap.append(EL_test.nextSibling);
EL_newWrap.prepend(EL_test);
EL(".containter").append(EL_newWrap);
div { padding: 10px; outline: 1px solid red;}
.newWrap { background: gold; }
<div class="containter">
  aaaa aaaa aaaa aaaa aaaa aaaa
  <div class="test">TEST</div>
  bbbb <i>bbbb</i> <span>bbbb</span> bbbb <br> bbbb <b>bbbb</b>
</div>

If the text is always at the end, this seems to work.

$('.test').each(function() {
  const thisEl = $(this);
  const content = thisEl.parent().contents();
  const text = content[content.length - 1];
  $(text).add(thisEl).wrapAll('<div class="pink">');
});
.container {
  border-top: 2px solid #ccc;
  margin-top: 10px;
  padding-top: 10px;
}

.pink {
  background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
  before before before before before before before before before before before
  <div class="test">TEST</div> after after after after after after after after
</div>

<div class="container">
  before before before before before before before before before before before
  <div class="other">between between</div>
  <div class="test">TEST</div> after after after after after after after after
</div>

<div class="container">
  <div class="other">way before</div>
  before before before before before before before before before before before
  <div class="other">between between</div>
  <div class="test">TEST</div> after after after after after after after after
</div>

Related