Will
Will

Reputation: 2121

Get text surrounding the matched element in jQuery

In the following HTML...

<p>abc<span class='blue'>def</span>ghi</p>

...I want to get the character of text immediately preceding the span element (in this case the letter c). Assume that the string between the p tags is of arbitrary contents and length, and that the span element could be anywhere in between the p tags. When the opening p tag is adjacent to the opening span tag, an empty string should be returned.

Is there a convenient way to retrieve such with jQuery?

Upvotes: 1

Views: 754

Answers (2)

David Thomas
David Thomas

Reputation: 253308

You can use:

var prevLetters = $('span.blue')[0].previousSibling.nodeValue,
    lastLetter = prevLetters.substring(prevLetters.length - 1);

var prevLetters = $('span.blue')[0].previousSibling.nodeValue;

var lastLetter = prevLetters.substring(prevLetters.length - 1);
console.log(lastLetter);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>abc<span class='blue'>def</span>ghi</p>

JS Fiddle demo.

This finds all the elements matching the selector and then, using the [0] notation, switches to the DOM node (rather than the jQuery object), and selects the previous sibling (a textNode) and finds its nodeValue.

This is then modified using the substring() to give only the last letter.


Edited: to meet the requirement of an empty string, if the span tag is the first child of the parent:

var prevLetters, lastLetter;
if ($('span.blue')[0].previousSibling) {
    prevLetters = $('span.blue')[0].previousSibling.nodeValue;
    lastLetter = prevLetters.substring(prevLetters.length - 1);
}
else {
    lastLetter = '';
}

var prevLetters, lastLetter;
if ($('span.blue')[0].previousSibling) {
  prevLetters = $('span.blue')[0].previousSibling.nodeValue;
  lastLetter = prevLetters.substring(prevLetters.length - 1);
} else {
  lastLetter = '';
}
console.log(lastLetter);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p><span class='blue'>def</span>ghi</p>

JS Fiddle demo.


Edited and turned into a function:

function prevLetter(elem){
    if (!elem){
        return false;
    }
    else {
        var prevLetters, lastLetter;
        if (elem.previousSibling){
            prevLetters = elem
                .previousSibling
                .nodeValue;
            lastLetter = prevLetters
                .substring(prevLetters.length-1);
        }
        else {
            lastLetter = '';
        }
    }
    return lastLetter;
}

var lastLetter = prevLetter($('span.blue')[0]);

function prevLetter(elem) {
  if (!elem) {
    return false;
  } else {
    var prevLetters, lastLetter;
    if (elem.previousSibling) {
      prevLetters = elem
        .previousSibling
        .nodeValue;
      lastLetter = prevLetters
        .substring(prevLetters.length - 1);
    } else {
      lastLetter = '';
    }
  }
  return lastLetter;
}

var lastLetter = prevLetter($('span.blue')[0]);
console.log(lastLetter);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>abc<span class='blue'>def</span>ghi</p>

JS Fiddle demo.

And, finally, a pure JavaScript answer which changes the selector from a jQuery selector, utilising document.querySelectorAll() where available, to a DOM selector utilising document.querySelectorAll() directly (all other code remains the same as in the function above):

var lastLetter = prevLetter(document.querySelectorAll('span.blue')[0]);
console.log(lastLetter);

// or:
var lastLetter = prevLetter(document.querySelector('span.blue'));
console.log(lastLetter);

The key difference between the last two is that querySelectorAll() returns a collection of elements, whether that collection has none, one or many elements - and therefore requires the use of an index to retrieve a particular element, whereas querySelector() returns only one – the first – matching Node, or null if no matching nodes were found.

References:

Upvotes: 3

Umesh Patil
Umesh Patil

Reputation: 10685

Here is the expected solution demo on jsfiddle:

Code as below:

var all=$("p").text(); // everything inside <p>
var sub=$("span ").text(); // everything inside <span>
var pos= all.indexOf(sub)-1; // place of just letter before span
alert(all[pos]);​

Upvotes: 0

Related Questions