October 5, 2006

I’ll burn this whole city down

In Safari 2.0 (and presumably all versions since 1.3), the javascript method window.getSelection() returns a Selection object, but not the same one that Mozilla/Gecko browsers return. Instead it is more of a bastardization of the DOM’s Range object. Of course, this isn’t documented anywhere. No, I found this by reading the source code for the window.getSelection method itself.

What’s perplexing is that WebCore does have a DOM-compatible Range implementation, and yet window.getSelection() still returns this not-quite Selection object instead. What’s even more amazing, is that the type property of this object (i.e.: window.getSelection().type) returns Range, even though it isn’t a Range! This is probably a bug.

The only workaround I found for this was here and suggests converting the Selection item in Safari to a string and working with it from there, but in my case there’s already code expecting a Range and so that method wouldn’t work. I had to dig to find out what the hell window.getSelection() was returning, and seeing how it was so hard for me to find, I figured I should publish it in case someone else needs it.

To save you the trouble, here’s a table with comparisons of Safari Selection objects properties/methods with the equivalents for the W3C/Mozilla implemented Range object, since that’s basically the equivalent and many of the field values (if not their names) are the same. Using this, you can write Safari specific JS that will pull what you need from Selection in place of a W3C compliant Range object.

Safari/AppleWebKit W3C/Mozilla
Properties:
anchorNode startContainer
anchorOffset startOffset
baseNode startContainer
baseOffset startOffset
focusNode endContainer
focusOffset endOffset
extentNode endContainer
extentOffset endOffset
isCollapsed collapsed
Methods:
setBaseAndExtent(start, end) setStart(start) and setEnd(end)
collapse() collapse()

I think I might start a “Friends don’t let friends use Safari” campaign.

Edit: So I ordered a copy of the O’Reilly fifth edition javascript book and they have what might be the best cop-out ever. From page 342, emphasis mine:

function getSelectedText() {
	if(window.getSelection){
		// This techniquge is the most likely to be standardized
		// getSelection() returns a Selection object, which we do not document.
		return window.getSelection().toString();
	}
 		/* … */
}

Posted by magicalgirl at 6:31 pm

Comments

I stopped using Safari a long time ago. From a non-developer standpoint, Safari is just not as compatible with other websites as Firefox (the gold standard). But, that goes for any WebCore-based browser also like OmniWeb, Shiira, etc. Oh wells, who needs those browsers when you have Firefox?

Comment by mookie — October 6, 2006 at 12:18 am

Apparently some people, since Safari 2.0 is considered Grade-A. I know some folks who prefer it because “Firefox on mac is slow and ugly”. But even if Firefox is, as you call it, “the gold standard” there are still something like 90% of Internet users who are using Internet Explorer so it really needs to be top priority. Thankfully debugging in Internet Explorer isn’t nearly as painful to do as in Safari, and there’s a lot more documentation.

Comment by alice — October 6, 2006 at 1:09 am

Thank a lot for your researches. Maybe you have anymore suggestions about how to make Rich text editor on safari? About *Caret* object for example?

Comment by liilliil — December 7, 2006 at 9:09 am

Powered by WordPress
Opinions expressed on this site are mine alone and do not represent those of my employer, my employer's business partners, my friends, family, or even trolls living under bridges.
Portions of this website may not work in Safari (and I really don't care).