19

Does anyone know of any cross-browser user selection range libraries written in javascript?

I found a few jQuery plugins, (which quite frankly are too limiting and very buggy).

I would just like to know what you have found out there. Don't send me googling this again, (I've spent days working on all this). Hopefully, this can be where future programmers can find the answer.

Mechlar
  • 4,946
  • 12
  • 58
  • 83
  • 1
    Both of your links `http://plugins.jquery.com/project/wrapSelection` and `http://perplexed.co.uk/1020_text_selector_jquery_plugin.htm` doesn't work any more. Can you update them? – John Aug 25 '16 at 15:05
  • update your links, please – oldboy Nov 11 '17 at 22:36

3 Answers3

40

I've developed a cross-browser Range and selection library called Rangy. Its core is not dissimilar in concept to IERange but goes beyond it in terms of implementation of the DOM level 2 Range and HTML5 selection specifications, and also in terms of stability and workarounds for browser bugs. I think it's the best there is out there.

There are also extra modules for saving, restoring and serializing selections and applying CSS class to ranges and selections.

https://github.com/timdown/rangy

The following uses some Rangy extensions to Ranges to easily iterate over text nodes within a selection and surround each one:

function surroundSelectedText(templateElement){
    var range, sel = rangy.getSelection();
    var ranges = sel.getAllRanges();
    var textNodes, textNode, el, i, len, j, jLen;
    for (i = 0, len = ranges.length; i < len; ++i) {
        range = ranges[i];
        // If one or both of the range boundaries falls in the middle
        // of a text node, the following line splits the text node at the
        // boundary
        range.splitBoundaries();

        // The first parameter below is an array of valid nodeTypes
        // (in this case, text nodes only)
        textNodes = range.getNodes([3]);

        for (j = 0, jLen = textNodes.length; j < jLen; ++j) {
            textNode = textNodes[j];
            el = templateElement.cloneNode(false);
            textNode.parentNode.insertBefore(el, textNode);
            el.appendChild(textNode);
        }
    }
}

var span = document.createElement("span");
span.style.color = "green";
span.style.fontWeight = "bold";

surroundSelectedText(span);
Flimm
  • 136,138
  • 45
  • 251
  • 267
Tim Down
  • 318,141
  • 75
  • 454
  • 536
2

For the jQuery plugin option there's jCaret, you can check out the homepage here and the examples here.

I've used this on a few projects for various applications, works well at removing the cross-browser inconsistencies.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • Looks great, however it only works in inputs and textareas. I have been working on converting it to work on any element but no dice yet. One of the main features is that I need to be able to wrap spans (and any other element I specify) around a user selection. The wrapSelection code (http://plugins.jquery.com/project/wrapSelection) works perfect and I've modified it for my needs, however, the code for some reason doesn't work in IE8, even though it boasts support for IE. – Mechlar Aug 11 '10 at 14:43
1

For general-purpose range work (as opposed to input/textarea selection handling), consider ierange. Attempts to implement the standard DOM Level 2 Range model supported by other browsers in IE. Kind-of works.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • One of the main features I need is to surround a selection with a span. This code can do that but it doesn't handle wrapping a span around a selection that overlaps other end tags. – Mechlar Aug 11 '10 at 14:39
  • 1
    Well, such a thing would be impossible, of course! A span, like any element, must have a single parent. If you wanted to add a highlight to a stretch of text whose endpoints were not inside the same element, you would have to walk over each element in the selection adding a separate `` element around each element whose parent isn't completely contained within the selection. (Or you could do it simply by wrapping each non-whitespace Text node between the endpoints.) – bobince Aug 11 '10 at 15:55
  • I have gone some way to implementing a feature in Rangy (see my answer) that will apply formatting to a selection by surrounding each text node within the selection with a span, also removing and merging adjacent identical spans where appropriate. I'm hoping to release that within a few weeks. – Tim Down Aug 11 '10 at 16:05
  • Precisely, its not impossible. That is what wrapSelection() does. Only is doesn't work in IE8. – Mechlar Aug 11 '10 at 16:27