6

I have two divs as shown below:

<div id="div1">
<p>something</p>
<div><table><tr><td>Div1</td></tr></table></div>
</div>
<div id="div2">
<p>something else</p>
<div><table><tr><td>Div2</td></tr></table></div>
</div>
<button type="button">Check</button>

Now, I want to know when some text is selected and then the button pressed, if the selected text is under "div1" or not. How can I do that?

Edit: And the solution has to work in IE-7 and above.

srinath
  • 101
  • 1
  • 6

3 Answers3

23

2022 answer

The elementContainsSelection() function below returns a boolean representing whether the specified element contains the whole of the user's selection and works in all modern browsers.

function elementContainsSelection(el) {
    var sel = window.getSelection();
    if (sel.rangeCount > 0) {
        for (var i = 0; i < sel.rangeCount; ++i) {
            if (!el.contains(sel.getRangeAt(i).commonAncestorContainer)) {
                return false;
            }
        }
        return true;
    }
    return false;
}
<input type="button" onmousedown="alert(elementContainsSelection(document.getElementById('cake')))" value="Selection contained in 'slice of cake'?">

<div contenteditable="true">
    Cup of tea and a <b id="cake">slice of cake</b>
</div>

2011 answer

The elementContainsSelection() function below returns a boolean representing whether the specified element contains the whole of the user's selection and works in all major browsers, including IE 6.

Live demo: http://jsfiddle.net/eT8NQ/

Code:

function isOrContains(node, container) {
    while (node) {
        if (node === container) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}

function elementContainsSelection(el) {
    var sel;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount > 0) {
            for (var i = 0; i < sel.rangeCount; ++i) {
                if (!isOrContains(sel.getRangeAt(i).commonAncestorContainer, el)) {
                    return false;
                }
            }
            return true;
        }
    } else if ( (sel = document.selection) && sel.type != "Control") {
        return isOrContains(sel.createRange().parentElement(), el);
    }
    return false;
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • No neet to define a function isOrContains, Node.contains() already cover this case. The contains() method of the Node interface returns a boolean value indicating whether a node is a descendant of a given node, that is the node itself, one of its direct children (childNodes), one of the children's direct children, and so on. – Son Tr. Jun 14 '22 at 04:06
  • @SonTr. That's certainly true now but wasn't in 2011. I'll add a note to the answer. – Tim Down Jun 14 '22 at 11:34
0

you could observe a mouseup event on each div, and bind the following method to it:

var endpoint = null
function getselected(event){
  endpoint = event.target;
  var t = '';
  if(window.getSelection){
    t = window.getSelection();
  }else if(document.getSelection){
    t = document.getSelection();
  }else if(document.selection){
    t = document.selection.createRange().text;
  }
  return t;
}

this method will then return the selected text, it will tell you that the selection process ended on the div that fired the event. if you need the startpoint to, you have to bind a mousedown event to the divs, that will store the elements id in a variable, so you can determine the start- and endpoint of the selection process and find out which divs lie in between.

var startpoint = null;
function beginSelection(event){
  startpoint = event.target;
}

if the getSelected-method returns an empty string, you should reset start- and endpoint.

zuloo
  • 1,310
  • 1
  • 8
  • 12
0

something like:

function checkSelection() {
    function checkNode(node) {
        do {
            if(node.id == "div1")
                return true;
        } while(node = node.parentNode);

        return false;
    }

    if(window.getSelection) {
        var selection = window.getSelection();
        for(var i = 0, l = selection.rangeCount; i < l; i++) {
            var range = selection.getRangeAt(i), start = range.startContainer, end = range.endContainer;
            if(checkNode(start) || (start != end && checkNode(end)))
                return true;
        }
    }

    if(window.scelection && window.selection.createRange) {
        var range = window.selection.createRange();
        if(range)
            return checkNode(range.parentElement());
    }

    return false;
}