Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to support multiple text selections cross browser?

I am building a web-based annotation tool, where end users can select and annotate a section of text from an HTML document. Programmatically speaking, accessing and working with the selected text and corresponding range is straightforward using "window.getSelection" and "getRangeAt".

I am running into a problem, however, when I try to put all of this together in a cross-browser application. Everything works find in Firefox, but in Safari I noticed immediately that when I click on an HTML Button (i.e. the "annotation" button), the current user text selection goes away, as if clicking on the button repositioned the text caret. My code that attempts to access the window.getSelection executes from a script in this button, which then reports that no selection exists.

I dug in and took a look at how Google Docs, specifically their word-processing application handles this, as essentially the behavior and mechanics of selecting text and clicking "Bold" or "Change Font" corresponds to my annotation function. In Google Docs, they load the text of the document to be edited into an iframe. Playing around with this, I learned that Firefox out-of-the-box supports multiple selection ranges in a web page that contains multiple frames, or iframes. In other words, I can select a section of text in the base page, and a separate section of text in the iframe without the first selection disappearing. This Google Docs solution works for both Firefox and Safari (the two browsers that I'm interested in). But when I built a simple example page to test this solution, it would not work in Safari. As soon as I click a button or make text selection in the root page (outside of the iframe) the current iframe selected text goes away.

Anyone know what I'm missing here to get this to work? Or have a suggestion on another way to get this to work?

like image 826
user14636 Avatar asked Mar 23 '09 17:03

user14636


3 Answers

Hook your event handler up to the button's mousedown event (instead of the click or mouseup event). This will allow you to grab the current selection before it is cleared.

You can maintain user experience by storing the selection in a variable and only using it the if your button receives a click event. Like this:

<button onmousedown="sel = window.getSelection()" onclick="alert(sel)">What's the selection?</button>
like image 66
s4y Avatar answered Oct 27 '22 20:10

s4y


Off the top of my head, I think your easiest solution would be to attach an event handler to text selection and save the current selection to a buffer, this way you don't have to worry about timing.

Open up firebug on this page and run the following snippet:

var buffer = '';
$('p').mouseup(function() {
    buffer = window.getSelection();
});

You can then select whatever you want and see the last selected text by running:

console.log(buffer);

Voila, click/deselect timing problem solved :)

like image 33
Micah Snyder Avatar answered Oct 27 '22 21:10

Micah Snyder


I learned that Firefox out-of-the-box supports multiple selection ranges in a web page that contains multiple frames

Hell, Firefox even supports multiple selections on a single frame! (Try click-drag then ctrl-click-drag on a separate piece of text.)

in Safari I noticed immediately that when I click on an HTML Button the current user text selection goes away, as if clicking on the button repositioned the text caret

Works for me, in Safari 3.2.1 on Windows. Clicking a <button>, <input type="button"> or <a> leaves the selection where it is, albeit greyed out if it's in a different frame. ‘window.getSelection()’ continues to work as usual.

Can you post a test case and what Safari version makes it misbehave?

like image 29
bobince Avatar answered Oct 27 '22 20:10

bobince