Mark Fletcher
Mark Fletcher

Reputation: 751

Get selected text with a div, with arbitrary nested divs

Using javascript, I'd like to get the selected text within a div. My question is almost the same as Get selected text from only one div except that within the div there may be an arbitrary number of other nested divs. The answer to that question only works for one nested div.

In other words, say I have a div, STUFF. STUFF could be arbitrary HTML, including plenty of other nested divs. I want the selected HTML within the forkfork div, including any selected nested divs.

Updated: Here's some code, adapted from the previous question. I want to be able to select anything within the "forkfork" div, and have it returned, ideally the raw HTML.

<html>
<body>
<div id="forkfork">want to be able to select anthing within here
    <div id="child">or in here</div>
    <div id="child1">perhaps in here,
        <div id="child2">maybe in here,
            <div id="child3">or in here
            </div>
        </div>
    </div>
    though here.
</div>
<div id="b">don't want to have this returned.</div>

<button id="btn">btn
<script>
function select() {
    var flag = 0;
    sel = window.getSelection();
    for (var i = 0; i < sel.rangeCount; i++) {
        var s = sel.getRangeAt(i).startContainer.parentNode.id;
        var e = sel.getRangeAt(i).endContainer.parentNode.id;
        if (s == "forkfork") flag = 1;
        if (flag = 1 && e == "forkfork" || e == "child") flag = 2;
    }

    if (flag == 2) alert(sel);

}

document.getElementById("btn").addEventListener("click", function () {
    select();
});
</script>
</body>

And a jsfiddle: http://jsfiddle.net/4n3ud3nb/1/

Upvotes: 2

Views: 1346

Answers (2)

talves
talves

Reputation: 14353

Using cloneContents() from the range the contents of the selection could be returned.

The first cloneContents call will return the contents if there was an over run of our targeted element forkfork.

If we find no over run of the selection, we will check to make sure our selection starting range is a child of the targeted element.

Here is the example snippet:

function select(event) {
  var sel;
  //console.log(document.getSelection);
  if (document.getSelection) 
    sel = document.getSelection();
  else
    sel = document.selection.createRange();
  //console.log('sel',sel);
  var selText = '';
  var forkfork = document.getElementById("forkfork");
  if (sel.rangeCount > 0) {
    var range = sel.getRangeAt(0);
    var clonedSelection = range.cloneContents().querySelector("#forkfork");
    if (clonedSelection) {
      selText = clonedSelection.innerHTML;
    } else {
      clonedSelection = range.cloneContents();
      var startNode = sel.getRangeAt(0).startContainer.parentNode;
      //console.log(isChild(startNode, forkfork));
      if (isChild(startNode, forkfork)) {
        var div = document.createElement('div');
        div.appendChild(clonedSelection);
        selText = div.innerHTML;
      }
    }
  }

    alert(selText.toString());
}

function isChild(child, parent) {
  if (child === parent) return true;
  var current = child;
  while (current) {
    if (current === parent) return true;
    current = current.parentNode;
  }
  return false;
}

document.getElementById("btn").addEventListener("click", select);
#a {
  background: #C0D9AF;
}
#b,#b2 {
  background: #ECC8EC;
}
#c {
  background: #AFEEEE;
}
<div id="b">don't want to have this returned.</div>
  <div id="forkfork">want to be able to select anthing within here
    <div id="child">or in here</div>
    <div id="child1">perhaps in here,
      <div id="child2">maybe <strong>in</strong> here,
        <div id="child3">or in here</div>
      </div>
    </div>
    though here.
  </div>
  <div id="b2">And, don't want to have this returned.</div>

  <button id="btn">btn</button>

Upvotes: 1

Kedar
Kedar

Reputation: 1698

.innerHTML will return everything inside the div.

(function() {
    $(document).ready(function() {
        var x = document.getElementById('forkfork').innerHTML;
        console.log(x);
    });
}());

console.log(x) Will output this:

want to be able to select anthing within here
    <div id="child">something else</div>
    <div id="child1">another thing,
        <div id="child2">and another thing,
            <div id="child3">and another thing
            </div>
        </div>
    </div>
    though here.

If you want all text:

(function() {
    $(document).ready(function() {
        var x = $('#forkfork').text();
        console.log(x);
    });
}());

Which will output:

want to be able to select anthing within here
    something else
    another thing,
        and another thing,
            and another thing



    though here

Upvotes: 0

Related Questions