21 Jul

two konqueror js workarounds

In the evenings, I work on my KFM project – an ajax file manager. One of the current challenges is getting it to work in Konqueror.

I managed to overcome two head-wreckers yesterday – broken support for oncontextmenu, and no support for window.getSelection().removeAllRanges().

clearing the selected range

I’ll explain the latter first, as it was surprisingly simple in the end.

click here, then drag from the bottom right of the files area to the top left. note that the resulting rectangle surrounds some text, but the text is not selected (ie; not highlighted). That is the required result.

To do that in IE and Firefox, you simply empty the selection upon mousemove. For Firefox, that’s window.getSelection().removeAllRanges(), and for IE, that’s document.selection.empty();.

There is no equivalent for Konqueror, so I needed to wrack my brains to come up with a workaround.

In the end, it was bloody simple – when the dragging starts, create a transparent layer which floats above everything, and covers the entire window! That way, you simply cannot select anything if you want! When the drag is completed, simply remove the layer and carry on as normal.

contextmenu

This was a bit harder to workaround, but only because I couldn’t find any documentation that explained why it wasn’t working as expected.

The usual way to open a contextmenu is to attach an oncontextmenu event trigger to an element, then when it is triggered, you cancel the window’s default behaviour with e.preventDefault(), where e is the event (e.returnValue=false in IE).

Unfortunately, tests showed that in the case of Konqueror, oncontextmenu triggered the default behaviour before the script could prevent it.

I had to sit back and really think about this.

What is oncontextmenu? It is a trigger which activates when the right mouse button is clicked.

Upon onmouseup, the default behaviour rudely intrudes, so we need to use onmousedown instead, and cancel the default behaviour.

Now, I hate to write code that forks, so I tend to keep browser-specific code in completely separate files, where those browsers can override the correct functions with their own shoddy hacks. For example, on the KFM project, here is the main code, here are the IE-specific functions, and here are the Konqueror-specific functions.

Note the browser-specific versions of addEvent().

Correct (Firefox):

function addEvent(o,t,f) {
	o.addEventListener(t,f,false);
}

Internet Explorer:

function addEvent(o,t,f) {
	o['e'+t+f]=f;
	o[t+f]=function(){o['e'+t+f](window.event);}
	o.attachEvent('on'+t,o[t+f]);
}

Konqueror:

function addEvent(o,e,f){
	switch(e){
		case 'click':{
			f=(function(f){return function(e){if(e.button==1)f(e)}})(f);
			break;
		}
		case 'contextmenu':{
			e='mousedown';
			f=(function(f){return function(e){if(e.button==2){e.preventDefault();f(e)}}})(f);
			break;
		}
	}
	o.addEventListener(e,f,false);
}

There y’are. Took me hours to think those up. You get them for nothing.