Extension integration: Rainbowpicker
This is the first in a series of posts about integrating extensions with other extensions. That is, providing advanced functionality in your extension based on the presence of other extensions.
Rainbowpicker is an extension that changes the way XUL colorpickers work - for button type colorpickers, instead of the default behaviour where a drop down is displayed, it opens a more advanced dialog. It does this automatically for all <colorpicker type="button"/>s, which is good, but what if you want to provide this advanced functionality for places when you use normal (non-button) colorpickers?
The first thing we need to do is determine if Rainbowpicker is installed. If it’s installed, we’ll provide its functionality. If not, we’ll use the regular colorpicker.
This is easy if we’re in a browser overlay. Rainbowpicker adds functions to the overlay, so we could just detect the existence of those functions. However, to save some code (I’ll explain later) we’ll do it another way. Rainbowpicker does its magic by XBL, so if it’s installed it’ll change the binding for the button colorpicker. We’ll add a hidden button colorpicker and check its binding.
XUL:
<colorpicker id="rainbowpicker-detect" type="button" onchange="insertRainbowPickerColor(event)"/>
CSS:
#rainbowpicker-detect {
display: none;
}
JS:
var rainbowPicker = document.getElementById("rainbowpicker-detect");
if (getComputedStyle(rainbowPicker, "").MozBinding == "url(chrome://rainbowpicker/content/colorpicker.xml#colorpicker-button)") {
//rainbow picker is installed
}
Now that we know whether Rainbowpicker is installed, we can provide the best functionality available. We’ll include both the elements for use with and without Rainbowpicker, hiding the Rainbowpicker-specific elements by default. If we detect that Rainbowpicker is installed, we’ll show the Rainbowpicker-specific elements and hide the others.
Elaborating on the JS above:
var rainbowPicker = document.getElementById("rainbowpicker-detect");
if (getComputedStyle(rainbowPicker, "").MozBinding == "url(chrome://rainbowpicker/content/colorpicker.xml#colorpicker-button)") {
document.getElementById("pick-color-rainbowpicker").style.display = "-moz-box";
document.getElementById("pick-color").style.display = "none";
}
This of course assumes the existence of #pick-color-rainbowpicker and #pick-color.
How do we make #pick-color-rainbowpicker show Rainbowpicker’s dialog? We could directly call openDialog with the correct parameters, but this could change in the next version of Rainbowpicker and it would dupicate code. Instead, we’ll call showDialog on a hidden colorpicker. This is where the code savings I mentioned earlier comes into effect: we already defined a hidden colorpicker, so we’ll just re-use it.
In #pick-color-rainbowpicker’s oncommand, we run document.getElementById('rainbowpicker-detect').showPopup(). We give #rainbowpicker-detect an onchange handler. In this handler, we check the color property of the target of the event. Unfortunately, there’s a bug in Rainbowpicker where onchange is fired twice. To get around it:
var rainbowPickerJustChanged = false;
function foo(event) {
//rainbowpicker does it twice...
if (rainbowPickerJustChanged) {
return;
}
rainbowPickerJustChanged = true;
setTimeout(function() {rainbowPickerJustChanged = false}, 100);
//do what you want with event.target.color
}
Seems like more work than it should be, doesn’t it? It also seems like it could break fairly easy - all it would take is Rainbowpicker’s XBL getting moved to a different path. I contacted the author of Rainbowpicker. Based on my suggestions, he said he’ll fix the double onchange bug and consider adding an API to do all of this. Extension authors love feedback, especially the technical kind. Don’t be afraid to ask.
May 23rd, 2007 at 1:38 am
here is another good colorpicker for .net users
http://www.xcess.info/xcesscolorpicker