Reputation: 2121
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
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>
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>
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>
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
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