User:Catrope/Bizarre browser bugs

Opera does a couple of annoying brain-damaged things that makes web developers go crazy. If someone ever starts serial-killing Opera developers, here's why:

Newline handling
The representation of newlines varies over browsers. For instance, Firefox represents newlines as  (even on Windows), while IE represents them as. Both browsers seem to be tolerant when trying to insert text in the 'wrong' newline format, and automatically convert it. This means you can code JS quite nicely without having to worry about one browser saying a newline is one character while the other says it's two.

Since Opera is this schizophrenic browser torn between wanting to be a good browser and wanting to be like IE, it came up with the following compromise: when you grab the contents of a textarea using  or  , newlines are represented as   , i.e. as one character. However, when manipulating selections using  or   (Opera, in its schizophrenia, supports both the Gecko way and the IE way), newlines are treated as two characters (presumably  ). This means that the following snippet doesn't do what you expect in Opera: In Firefox, this would search for the string "foo" in the textarea and select it if found. It'll also work in IE if you replace the  assignment with something using a TextRange object. However, it won't work in Opera, because of the different newline representations: the selection will be off to the left by the number of newlines preceding the found occurrence of "foo".

To hack around this, you'd have to do  and then call. Of course, you only want to do this when you're sure you're on a broken version of Opera (to my knowledge, all current versions are broken, but they might fix it some day), so you need a function that tests for this brokenness, then conditionally replaces  with.

The code for this function can be found in this file in a function called.

Moving selections
Some older versions of Opera (I only tested this on 9.0, not sure about 9.4 or 10) are very picky about how selections are moved. A typical code snipper to select the 4th through the 8th character would be: This looks very intuitive and works fine... initially. However, changing the selection to (9, 13) afterwards using the same template doesn't do what you want: you end up selecting (4, 13).

The reason for this is that in between the selectionStart and the selectionEnd assignments, the selection would be (9, 4); that is, selectionStart would be moved past selectionEnd. All sane browsers that use selectionStart/End allow this and treat negative-length selections as selections of length zero; that is, if selectionEnd <= selectionStart the cursor is placed at selectionStart and nothing is selected. However, Opera is not flexible like that: it stubbornly refuses to set selectionStart past selectionEnd, and simply ignores the assignment. To work around that, you have to set selectionEnd first so selectionStart can be safely moved. However, assuming that this bug is symmetrical, moving selectionStart first is actually right when moving the selection back, so as to prevent moving selectionEnd back past selectionStart. This results in the following code: