2

code: http://jsfiddle.net/byHMP/2/

(note: when properly selected, the code will insert a span around the selection and change the background color)

Selection Code:

var html = "";

sel = window.getSelection(); // not sure how many browsers this works on.
var temp = document.createElement("div");

for (var i = 0, len = sel.rangeCount; i < len; ++i) {
    curr_range = sel.getRangeAt(i);

    temp.appendChild(curr_range.cloneContents());

    if (temp.innerHTML.length < MINIMUM_SELECTION_LENGTH) {
        return false;
    }

    var selection = document.createElement("span")
    //selection.id = content_hash;
    curr_range.surroundContents(selection);

    selection = $j(selection).addClass("highlighted");

}
html = temp.innerHTML;

so, right now, it'll only select within elements, and MAYBE if you cover an entire element and the text to the left and right of that...

Maybe I need to find a way to expand to the selection in a certain direction if the tags are unmatched? I just don't know. (Also, I wouldn't know how to do that. I mean, I can expand the selection to the overall parent element (a UL for example, when you just want to select multiple LIs, but I feel that is a bit overkill in most cases)

NullVoxPopuli
  • 61,906
  • 73
  • 206
  • 352
  • Could you be more specific as to the precise effect you're trying to achieve? Is it covered by any of these questions? http://stackoverflow.com/questions/3223682/change-css-of-selected-text-using-javascript/3224513#3224513, http://stackoverflow.com/questions/6285154/javascript-surroundcontents-on-selection-doesnt-work-as-expected-if-used-on-par/6286445#6286445 – Tim Down Nov 03 '11 at 20:23
  • the first one not so much. the second one explains my problem. If I have a selection containing an unmatched tag, couldn't I expand the selection until the selection has valid HTML (all tags matched)? – NullVoxPopuli Nov 03 '11 at 20:28
  • I'm not much clearer. If you're just looking to change the background colour for the whole selection then the first answer applies. If you want to apply arbitrary styling, my answer to the second question could help too. It probably isn't helpful to think of the selection as containing valid HTML or not; instead it's more helpful to think of it as a range in the document from one point to another, taking in several nodes on the way (with possibly partially selected nodes at each end). You can then act on each selected node (e.g. surrounding it in a span) in turn. – Tim Down Nov 03 '11 at 23:41

1 Answers1

2

The Range#surroundContents requires all selected elements to have their closest common ancestor element contained in the range. Otherwise, it throws a BAD_BOUNDARY_ERR.

To overcome this issue, you need something like the following.

var node = document.createElement(tagName);
var frag = range.extractContents();
node.appendChild(frag);
range.insertNode(node);
if (!range.collapsed) {
  range.removeContents()
}
J. K.
  • 8,268
  • 1
  • 36
  • 35
  • I'm aware of the error. Your code generates some curious behavior. If you cross divs, it splits the div, and creates a
    pair... is ok, just, not quite what I'm looking for. If there is a way to extend the selection so all the tags have matching ends., that would be ideal.
    – NullVoxPopuli Nov 03 '11 at 20:50
  • Yes, the code splits elements. It should be OK if you have only inline elements in the range. If there can be block elements, you need to iterate over them and create a smaller Range for each. – J. K. Nov 03 '11 at 20:53
  • Read the second half of my comment, you need to iterate over the block elements and manually surround contents of each in its own `node`. You will probably want to get the blocks with something like `frag.querySelectorAll('p, div, ...')` – J. K. Nov 03 '11 at 21:03
  • alright, I'm smellin what you're sizzlin'. Now, how do you un-do it? – NullVoxPopuli Nov 03 '11 at 21:08
  • Yeah, I'd like to know that too :-/ AFAIK the `execCommand('undo')` only works for stuff done with `execCommand`. – J. K. Nov 03 '11 at 21:12
  • hmmm. shoot. maybe we'd need to do vanilla string manipulation to do it =\ – NullVoxPopuli Nov 03 '11 at 21:14
  • I think issue is actually just CSS =\ (for the alignment) – NullVoxPopuli Nov 04 '11 at 13:52