views:

715

answers:

3

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?

A: 

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?

bobince
I can't reproduce with Safari Mac either.
Chuck
I can't reproduce the Firefox multi-select behavior you describe.
Guss
You need Firefox 3, and a page of plain HTML text that doesn't do anything funny with mouse events. (It doesn't work on SO's comment/answer areas, for example.) Click-drag-then-Ctrl-click-drag works for me in Windows and Linux; I suppose the key combo might differ on Mac, perhaps.
bobince
+2  A: 

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>
Sidnicious
+2  A: 

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 :)

dfltr