if (!dojo._hasResource["dojox.widget.ColorPicker"]) { // _hasResource checks
// added by build. Do
// not use _hasResource
// directly in your
// code.
dojo._hasResource["dojox.widget.ColorPicker"] = true;
dojo.provide("dojox.widget.ColorPicker");
dojo.experimental("dojox.widget.ColorPicker"); // level: prototype
dojo.require("dijit.form._FormWidget");
dojo.require("dojo.dnd.move");
dojo.require("dojo.fx");
dojo.declare("dojox.widget.ColorPicker", dijit.form._FormWidget, {
// summary: a HSV color picker - like PhotoShop
//
// description:
// provides an interactive HSV ColorPicker similar to
// PhotoShop's color selction tool. Will eventually
// mixin FormWidget and be used as a suplement or a
// 'more interactive' replacement for ColorPalette
//
// example:
//
// code:
// var picker = new dojox.widget.ColorPicker({
// // a couple of example toggles:
// animatePoint:false,
// showHsv: false,
// webSafe: false,
// showRgb: false
// });
//
// markup:
//
//
// showRgb: Boolean
// show/update RGB input nodes
showRgb : true,
// showHsv: Boolean
// show/update HSV input nodes
showHsv : true,
// showHex: Boolean
// show/update Hex value field
showHex : true,
// webSafe: Boolean
// deprecated? or just use a toggle to show/hide that node, too?
webSafe : true,
// animatePoint: Boolean
// toggle to use slideTo (true) or just place the cursor (false) on
// click
animatePoint : true,
// slideDuration: Integer
// time in ms picker node will slide to next location (non-dragging)
// when animatePoint=true
slideDuration : 250,
_underlay : dojo.moduleUrl("dojox.widget",
"ColorPicker/images/underlay.png"),
templateString : "
\n\t
\n\t\t\n\t\t\n\t
\n\t
\n\t\t\n\t\t\n\t
\n\t\n\t\n\t
\n\t\t
\n\t\t\t
\n\t\t\t
r
\n\t\t\t
g
\n\t\t\t
b
\n\t\t\t
\n\t\t
\n\t\t
\n\t\t\t
\n\t\t\t
h
°
\n\t\t\t
s
%
\n\t\t\t
v
%
\n\t\t\t
\n\t\t
\n\t\t
\t\n\t\t\thex: \n\t\t
\n\t
\n
\n",
postCreate : function() {
// summary: As quickly as we can, set up ie6 alpha-filter support
// for our
// underlay. we don't do image handles (done in css), just the
// 'core'
// of this widget: the underlay.
if (dojo.isIE && dojo.isIE < 7) {
this.colorUnderlay.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
+ this._underlay + "', sizingMethod='scale')";
this.colorUnderlay.src = dojo.moduleUrl("dojox.widget",
"FisheyeList/blank.gif").toString();
}
// hide toggle-able nodes:
if (!this.showRgb) {
this.rgbNode.style.display = "none";
}
if (!this.showHsv) {
this.hsvNode.style.display = "none";
}
if (!this.showHex) {
this.hexNode.style.display = "none";
}
if (!this.webSafe) {
this.safePreviewNode.style.display = "none";
}
},
startup : function() {
// summary: defer all additional calls until we're started, and our
// embeded sliders are loaded? (not implemented yet)
// this._offset = ((dojo.marginBox(this.cursorNode).w)/2);
this._offset = 0;
this._mover = new dojo.dnd.Moveable(this.cursorNode, {
mover : dojo.dnd.boxConstrainedMover({
t : 0,
l : 0,
w : 150,
h : 150
})
});
this._hueMover = new dojo.dnd.Moveable(this.hueCursorNode, {
mover : dojo.dnd.boxConstrainedMover({
t : 0,
l : 0,
w : 0,
h : 150
})
});
// no dnd/move/move published ... use a timer:
dojo.subscribe("/dnd/move/stop", dojo.hitch(this, "_clearTimer"));
dojo.subscribe("/dnd/move/start", dojo.hitch(this, "_setTimer"));
// ugly scaling calculator. need a XYslider badly
this._sc = (1 / dojo.coords(this.colorUnderlay).w);
this._hueSc = (255 / (dojo.coords(this.hueNode).h + this._offset));
// initial color
this._updateColor();
},
_setTimer : function(/* dojo.dnd.Mover */mover) {
this._timer = setInterval(dojo.hitch(this, "_updateColor"), 45);
},
_clearTimer : function(/* dojo.dnd.Mover */mover) {
clearInterval(this._timer);
this.onChange(this.value);
},
_setHue : function(/* Decimal */h) {
// summary: sets a natural color background for the
// underlay image against closest hue value (full saturation)
// h: 0..255
// this is not a pretty conversion:
var hue = dojo.colorFromArray(this._hsv2rgb(h, 1, 1, {
inputRange : 1
})).toHex();
dojo.style(this.colorUnderlay, "backgroundColor", hue);
},
_updateColor : function() {
// summary: update the previewNode color, and input values
// [optional]
var h = Math
.round((255 + (this._offset))
- ((dojo.style(this.hueCursorNode, "top") + this._offset) * this._hueSc));
var s = Math.round((dojo.style(this.cursorNode, "left") * this._sc)
* 100);
var v = Math.round(100
- (dojo.style(this.cursorNode, "top") * this._sc) * 100);
// limit hue calculations to only when it changes
if (h != this._hue) {
this._setHue(h);
}
var rgb = this._hsv2rgb(h, s / 100, v / 100, {
inputRange : 1
});
var hex = (dojo.colorFromArray(rgb).toHex());
this.previewNode.style.backgroundColor = hex;
if (this.webSafe) {
this.safePreviewNode.style.backgroundColor = hex;
}
if (this.showHex) {
this.hexCode.value = hex;
}
if (this.showRgb) {
this.Rval.value = rgb[0];
this.Gval.value = rgb[1];
this.Bval.value = rgb[2];
}
if (this.showHsv) {
this.Hval.value = Math.round((h * 360) / 255); // convert to
// 0..360
this.Sval.value = s;
this.Vval.value = v;
}
this.value = hex;
// anytime we muck with the color, fire onChange?
if (!this._timer && !(arguments[1])) {
this.setValue(this.value);
this.onChange(this.value);
}
},
_setHuePoint : function(/* Event */evt) {
// summary: set the hue picker handle on relative y coordinates
if (this.animatePoint) {
dojo.fx.slideTo({
node : this.hueCursorNode,
duration : this.slideDuration,
top : evt.layerY,
left : 0,
onEnd : dojo.hitch(this, "_updateColor")
}).play();
} else {
dojo.style(this.hueCursorNode, "top", (evt.layerY) + "px");
this._updateColor(false);
}
},
_setPoint : function(/* Event */evt) {
// summary: set our picker point based on relative x/y coordinates
if (this.animatePoint) {
dojo.fx.slideTo({
node : this.cursorNode,
duration : this.slideDuration,
top : evt.layerY - this._offset,
left : evt.layerX - this._offset,
onEnd : dojo.hitch(this, "_updateColor")
}).play();
} else {
dojo.style(this.cursorNode, "left", (evt.layerX - this._offset)
+ "px");
dojo.style(this.cursorNode, "top", (evt.layerY - this._offset)
+ "px");
this._updateColor(false);
}
},
// this ported directly from 0.4 dojo.gfx.colors.hsv, with bugs :)
// FIXME: use ttrenka's HSB ?
_hsv2rgb : function(/* int || Array */h, /* int */s, /* int */v, /* Object? */
options) {
// summary
// converts an HSV value set to RGB, ranges depending on optional
// options object.
// patch for options by Matthew Eernisse
if (dojo.isArray(h)) {
if (s) {
options = s;
}
v = h[2] || 0;
s = h[1] || 0;
h = h[0] || 0;
}
var opt = {
inputRange : (options && options.inputRange)
? options.inputRange
: [255, 255, 255],
outputRange : (options && options.outputRange)
? options.outputRange
: 255
};
switch (opt.inputRange[0]) {
// 0.0-1.0
case 1 :
h = h * 360;
break;
// 0-100
case 100 :
h = (h / 100) * 360;
break;
// 0-360
case 360 :
h = h;
break;
// 0-255
default :
h = (h / 255) * 360;
}
if (h == 360) {
h = 0;
}
// no need to alter if inputRange[1] = 1
switch (opt.inputRange[1]) {
case 100 :
s /= 100;
break;
case 255 :
s /= 255;
}
// no need to alter if inputRange[1] = 1
switch (opt.inputRange[2]) {
case 100 :
v /= 100;
break;
case 255 :
v /= 255;
}
var r = null;
var g = null;
var b = null;
if (s == 0) {
// color is on black-and-white center line
// achromatic: shades of gray
r = v;
g = v;
b = v;
} else {
// chromatic color
var hTemp = h / 60; // h is now IN [0,6]
var i = Math.floor(hTemp); // largest integer <= h
var f = hTemp - i; // fractional part of h
var p = v * (1 - s);
var q = v * (1 - (s * f));
var t = v * (1 - (s * (1 - f)));
switch (i) {
case 0 :
r = v;
g = t;
b = p;
break;
case 1 :
r = q;
g = v;
b = p;
break;
case 2 :
r = p;
g = v;
b = t;
break;
case 3 :
r = p;
g = q;
b = v;
break;
case 4 :
r = t;
g = p;
b = v;
break;
case 5 :
r = v;
g = p;
b = q;
break;
}
}
switch (opt.outputRange) {
case 1 :
r = dojo.math.round(r, 2);
g = dojo.math.round(g, 2);
b = dojo.math.round(b, 2);
break;
case 100 :
r = Math.round(r * 100);
g = Math.round(g * 100);
b = Math.round(b * 100);
break;
default :
r = Math.round(r * 255);
g = Math.round(g * 255);
b = Math.round(b * 255);
}
return [r, g, b];
}
});
}