Rey Bango

JavaScript, HTML, CSS & Random Stuff…

Update to the Google & Safari Double Firing mouseup Issue

Yesterday, I wrote about an issue I was having with Google & Safari’s way of handling text selection & the “mouseup” event versus Firefox & IE. I installed Opera 10.51 as well to ensure I tested this on the major browsers and Opera behaved just like Firefox & IE. So this was definitely specific to Chrome & Safari (and I assume Webkit as well).

It was an odd scenario but using a closure I found a workaround. This morning I was happy to see a comment from my friend Diego Perini with an explanation of what he feels is the cause and also an alternative fix.

you have setup an on “mouseup” event so it is normal it fires each time you release the mouse button. You are filtering “mouseup” to act only if a selection exists, that’s ok. Unfortunately the difference between the browsers you mention is that in Firefox the selection is cleared as soon as the next “mousedown” while in Safari/Chrome it is cleared on “mouseup” so when fired your filtering will still find a selection active on Safari/Chrome, thus the second alert you see.

This is how you can alternatively fix that problem, just add these lines:

function clearSelectedText() {
if (window.getSelection) {
window.getSelection().removeAllRanges();
} else if (document.getSelection) {
document.getSelection().empty();
} else {
var selection = document.selection && document.selection.createRange();
if (selection.text) {
selection.collapse(true);
selection.select();
}
}
}

addEvent(document, “mousedown”, clearSelectedText);

Hope this help fix it and explain what happens in Safari/Chrome, I wouldn’t mark this as a bug. Have fun.

This did in fact fix it and I like it much better because it avoids the need to attach a closure to an event, which could lead to a memory leak. Thanks Diego!

While this does provide a great workaround, it still leaves unanswered the reason that Chrome & Safari (and Webkit??) behave differently than IE, Firefox & Safari. I’m not sure if the expected behavior for “mouseup” & “mousedown” when selected text is present is clearly defined in a specification but this is just another example of how lack of consensus causes web developers to jump through hurdles for no clear reason.

My Solution to Google Chrome & Safari Double Firing the mouseup Event when Selecting Text

I needed to write a quick bit of code today to track when a user selects any text on a page. The key was to bind a method to the “mouseup” event which would grab the selected text and do something with it. This was plain ‘ole JS and thankfully Dean Edwards and Tino Zijdel had created a nice cross-browser event handler routine which worked great. And David Walsh has a nice post on similar functionality using MooTools & jQuery so I was able to leverage some of that code that deals with grabbing the selected text:

function findSelected() {
	if(window.getSelection) {
		return window.getSelection();
	}
	else if(document.getSelection) {
		return document.getSelection(); }
	else {
		var selection = document.selection && document.selection.createRange();
		if(selection.text) {
			return selection.text; }
		return false;
	}
	return false;
}

function getSelectedText() {
	var selected = findSelected();
	if(selected && (selected = new String(selected).replace(/^\s+|\s+$/g,''))) {
		alert( selected );
	}
}

From there it was just a matter of actually binding the method to “mouseup”:

addEvent(document,"mouseup",getSelectedText);

All of this seemed great and it worked perfectly in Internet Explorer and Firefox but when I tried it on Chrome, I found an issue. When I would select the whole line of text an alert box would appear which was expected but when I closed the box and clicked on any whitespace in the viewport, the alert box would reappear! To see it in action, try these steps:

  1. Using Chrome or Safari, open this page: http://reybango.com/ms/test.html
  2. Using your mouse select the whole line of the text and release. An alert box should appear.
  3. Close the alert box and click on any whitespace in the viewport.

In both Chrome and Safari, you should see that a second alert box is displayed containing the selected text. This doesn’t happen in Firefox or IE. It also won’t happen if you only select part of the text. It has to be the whole line.

After quite a bit of debugging, running it by John Resig & Pete Higgins and running short on time, I decided to create a work-around which resolved the issue. By using a closure to keep a persistent copy of the last selected text, I can compare that value to the newly selected text and if it matches the persistent copy, I can ignore it. It’s a very basic way to filter out the second call being done by Chrome & Safari:

getSelectedText = (function() {
	var selected = "";

	return (function() {
		var currSelection = findSelected();
		if (selected != currSelection) {
			selected = currSelection;
			if(selected && (selected = new String(selected).replace(/^\s+|\s+$/g,''))) {
				alert( selected );
			}
		}
	})
})();

Here’s the working demo.

Now I acknowledge that this is not the ideal solution and I need to determine what the browser inconsistency is here. It seems like it might be Webkit-related since it only affects Chrome & Safari so I’ll have to dig further into that. For now, though, the closure works and since I don’t do a circular reference between any DOM or JS objects, it looks like memory leaks shouldn’t be an issue.

Should a User Have a Choice When to Upgrade Their Browser?

I just did a post over on Ajaxian about Pingdom’s recent analysis of how frequently users upgrade their browsers. It’s a very conflicting topic for me which is why I chose to discuss it here.

From the report, it shows that Google’s Chrome has by far the fastest upgrade time of all the browsers, generally converting users within a month of a new release. This is primarily due to the browser’s use of automatic updating which has won accolades from many people in the development community who tend to cite IE6 still breathing as a great reason for having automatic updates.

This approach has both its merits and drawbacks. The obvious positive is that a user will receive important updates immediately ensuring that they will theoretically have a safer and more stable experience. The downside is that an update could actually mess up the browser (or computer) altogether as has happened on many occasions with antivirus programs. In addition, users no longer control the experience. Having worked at Mozilla, I know that they feel strongly that the user should have the ultimate choice of what goes on their computer. And I see the same thing now at Microsoft (where I’m now employed) and even Apple, where force-fed updates aren’t part of the process. They give users and companies the flexibility to decide when upgrading is right for them which I feel is extremely important. Obviously, the downside of the latter approach is that users are less inclined to actually upgrade, thus placing us into a situation where the 10-year old IE6 is still haunting us.

This is a tough situation because while users should have control, when they don’t upgrade it stifles developer abilities to push the web forward and can put these users at risk. I’m sure that the browser makers would be interested in your thoughts. What’s your take on this?

Full Disclosure: I previously worked at Mozilla and I am now employed at Microsoft.

3 Firefox Security Issues Fixed

CNet is reporting that Mozilla has released an update to Firefox which patches 3 critical security issues:

The first cross-site request forgery vulnerability could allow an attacker to generate a fake HTTP Referer header by exploiting a timing condition when setting the window.location property….
The second cross-site request forgery concerns the jar zip format enabling web sites to load pages packaged in zip archives containing signatures in java-archive format.

More info about the issue can be found on CNet's article and the update is available for download via Mozilla Firefox's site.

THE BIG LIST!

My BIG LIST of JavaScript, CSS & HTML Development Tools, Libraries, Projects, and Books.

Constantly updated with the latest and greatest tools. Check it out!

Contact Me

AIM: iamreybango
GTalk: reybango at gmail dot com
GMail: reybango at gmail dot com
Twitter: @reybango


Twitter

Rey Bango is Digg proof thanks to caching by WP Super Cache