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\n\t\t\t\n\t\t\t\n\t\t\t
r
g
b
\n\t\t
\n\t\t
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t
h °
s %
v %
\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("dojo","resources/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]; } }); }