Some things in the specs have behaviours that browser makers are required to adhere to. But other areas are a bit gray, where there is no definite guidance on implementation, so sometimes the behaviour is different from browser to browser.
Below you’ll find four screencasts showing the behaviour of different browsers when using this method. In these brief videos, I’ll be showing you what happens using this JS Bin demo, which you can see embedded here, and which you can test yourself:
Note: The goal here is to make the text in the field selectable when focusing with the mouse, while still allowing the user to deselect and edit the text, should the need arise. Focusing by tabbing into the field will always select the full text, regardless of the presence of the
What happens in Chrome?
- When the cursor is clicked (focused) into the text field, the text is momentarily all selected.
- It then quickly deselects, allowing the user to type at the location clicked within the field.
(The same behaviour occurs in the latest Safari on OSX and Windows 7.)
Notice the different behaviour in Firefox:
- The first click into the text field does exactly what Chrome did (momentary select then deselect and prepare to type).
- The second time you click into the text field, however, all the text is selected and it stays that way.
- Subsequent clicks alternate between nullifying the selection and keeping the selection.
In IE11, the behaviour seems to be more sensible:
- All the text is selected and stays selected each time you click into the field.
- You can choose to deselect inside the field to edit the text (which, for some reason, wasn’t working in the “edit” view in JS Bin in IE11).
- Exact same behaviour as IE11, including the ability to deselect and edit inside the field (but no bug in JS Bin).
What’s the Solution?
If you noticed in the code, I’m using the
onfocus event to trigger the
select() method on the input. A quick Google search turned up this StackOverflow thread, where the top-voted answer recommends using the
onmouseup event instead of
onfocus to overcome the problem of the text instantly deselecting.
The problem with this solution, however, is that if you try to deselect the text inside the field, it fails and instead just keeps selecting the full text over and over again (unless you use your keyboard to edit the text, which works fine). This is pointed out in this 2008 bug report. That bug’s status is set to “ExternalDependency”. I’m not completely sure what that means, but maybe someone familiar with those terms can let us know.
The truth is, I’m not so sure this is a bug since I don’t think there is a requirement for how this should be handled. It is annoying to see this difference in implementations, since it is logical that we as developer would prefer to see the same behaviour across the board.
Can’t we just set this handler initially and then remove it after it’s first call? And then again set it to run once as the blur event happens.
A dirty draft example that seems to work fine.
We still don’t know what is the correct browser behavior, but at least we can make it the same in every browser.
This is interesting because your solution works in Chrome but we get the same behaviour in Firefox.where the text is selected every 2nd entrance into the field (see 2nd screencast above).
Very funny… I didn’t notice that before sharing a link, but now I can reproduce this problem. Maybe it needs more investigation to make it work…
setTimeout fixes it for me. And honestly I don’t know why.
External dependency probably is referring to the way that form elements in the browser are rendered and controlled by the OS. A select element looks and acts slightly different on mac VS windows 8 VS windows XP.
“Assumptions about form elements — Since these HTML elements are created by the operating system directly, rather than by the browser, even for the same browser they can look different, have different sizes and behaviors, between operating systems. Styling these elements reduces the variability, but some of the form elements (like the input type=”file”) cannot be styled. Just give them a large buffer in your layout.”
You can use setTimeout with 0 in the onfocus event to get the same behavior in all browsers.
Interesting, it works perfectly in Chrome:
But Firefox still has the exact same behaviour shown in the 2nd screencast above. You can correct it in FF by using a timer or 100ms, but it isn’t perfect. Sometimes it doesn’t work, and you can still see it blinking to deselect for a moment, which would be a little annoying I think.
Nice solution for Chrome, though, thanks.
Styling these elements reduces the variability
To my mind, reading the spec, IE and Opera gets this right. Firefox almost gets it right and I would really appreciate it if you could log a bug pointing to this post and what you have found. Thanks!
(probably not the greatest bug report, esp. since JS Bin isn’t really a great RTC platform, but that’s all I have time for right now.)
Can’t we use jQuery’s event handlers to solve this problem ?