3

How could I get the text of the body that is before a specific element using Javascript/jQuery? What I want to achieve is finding out the position of an element respect of the body, for instance, if the body text is 100 characters long and the text before the node is 50, that node would be at 50%. Getting body's length is easy, but getting the text before an element is not as trivial as I'd thought in first instance.

EDIT:

To make it clear, I'll give an example:

<body> <p> ...some text <span>that could have sub-elements</span> </p> <p> ...some text <ul> <li>now with a list</li> <li>why not?</li> </ul> </p> <div> <p>...some text...</p> <div> <p>...some text...</p> <p id="this_is_the_element">what's there in the body before this element?</p> <p>...some text...</p> <p>...some text...</p> </div </div> </body> 

In this case, the specific node would be #this_is_the_element and what I would expect to get is something like:

...some text that could have sub-elements ...some text now with a list why not? ...some text ...some text 
1
  • 1
    Can you include some HTML to illustrate what you want to achieve? Commented Nov 14, 2012 at 10:02

2 Answers 2

5

I can propose this function :

​function textUntil($element) { var T = '#~~~#'; var $marquer = $('<span>'+T+'</span>'); $marquer.insertBefore($element); var text = $(document.body).text().split(T)[0]; $marquer.remove(); return text; } 

The trick is to insert a unique marker and get the text until this marker. Of course the inserted element is removed before the HTML is rendered. It will work for any kind of body.

Demonstration (open the console)

EDIT :

Demonstration with the HTML of your edit (open the console)

Sign up to request clarification or add additional context in comments.

Comments

0

Denys's answer will work most of the time, but it will not work correctly if the original text contains the same string of characters you chose to use for your marker.

I propose a different approach, using Ranges. Ranges are supported on all major browsers, including IE 9.

Here is my solution:

const rangeBefore = document.createRange() rangeBefore.setStart(parent.firstChild, 0) rangeBefore.setEndBefore(targetEl) const textBeforeTarget = rangeBefore.toString() 

And if you want all text after the element:

const rangeAfter = document.createRange() rangeAfter.setStartAfter(targetEl) rangeAfter.setEndAfter(parent) const textAfterTarget = rangeAfter.toString() 

And here is my answer adapted to your question:

const parent = document.querySelector("#common-ancestor") const targetEl = document.querySelector("#target") const rangeBefore = document.createRange() rangeBefore.setStart(parent.firstChild, 0) rangeBefore.setEndBefore(targetEl) const textBeforeTarget = rangeBefore.toString() document.querySelector("#output").textContent = textBeforeTarget
<div id="common-ancestor"> <p> ...some text <span>that could have sub-elements</span> </p> <p> ...some text <ul> <li>now with a list</li> <li>why not?</li> </ul> </p> <div> <p>...some text...</p> <div> <p>...some text...</p> <p id="target">what's there in the body before this element?</p> <p>...some text...</p> <p>...some text...</p> </div> </div> </div> <hr> Text before element:<br><pre id="output"></pre>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.