ColorPicker.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.widget.ColorPicker"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.widget.ColorPicker"] = true;
  8. dojo.provide("dojox.widget.ColorPicker");
  9. dojo.experimental("dojox.widget.ColorPicker"); // level: beta //TODO: which?
  10. dojo.requireLocalization("dojox.widget","ColorPicker", null, "ROOT,ar,az,bg,ca,cs,da,de,el,es,fi,fr,he,hr,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw");
  11. dojo.requireLocalization("dojo.cldr","number", null, "ROOT,af,af-na,ak,am,ar,ar-qa,ar-sa,ar-sy,ar-tn,ar-ye,as,asa,az,az-cyrl,be,bem,bez,bg,bm,bn,bo,brx,bs,ca,cgg,chr,cs,da,dav,de,de-at,de-ch,de-li,ebu,ee,el,el-cy,en,en-au,en-be,en-bw,en-bz,en-gb,en-ie,en-in,en-jm,en-mt,en-na,en-nz,en-tt,en-us-posix,en-za,en-zw,eo,es,es-419,es-cl,es-do,es-ec,es-gt,es-hn,es-mx,es-ni,es-pa,es-pe,es-pr,es-py,es-sv,es-us,es-uy,es-ve,et,eu,fa,fa-af,ff,fi,fil,fo,fr,fr-be,fr-ca,fr-ch,fr-lu,ga,gl,gsw,gu,guz,gv,ha,haw,he,hi,hr,hu,hy,id,ig,ii,in,is,it,it-ch,iw,ja,jmc,ka,kab,kam,kde,kea,khq,ki,kk,kl,kln,km,kn,ko,kok,ksb,kw,lg,lt,luo,luy,lv,mas,mer,mfe,mg,mk,ml,mo,mr,ms,ms-bn,mt,my,naq,nb,nd,ne,nl,nl-be,nn,no,nr,nso,nyn,om,or,pa,pl,ps,pt,pt-pt,rm,ro,rof,ru,rw,rwk,saq,seh,ses,sg,sh,shi,shi-tfng,si,sk,sl,sn,so,sq,sr,sr-latn-me,sr-me,ss,st,sv,sw,sw-ke,ta,te,teo,th,ti,tl,tn,tr,ts,tzm,uk,ur,ur-in,uz-af,uz-arab,ve,vi,vun,xh,xog,yo,zh,zh-hant,zh-hant-hk,zh-hk,zu");
  12. dojo.require("dijit.form._FormWidget");
  13. dojo.require("dojo.dnd.move");
  14. dojo.require("dojo.fx");
  15. dojo.require("dojox.color");
  16. dojo.require("dojo.i18n");
  17. (function(d){
  18. var webSafeFromHex = function(hex){
  19. // stub, this is planned later:
  20. return hex;
  21. };
  22. dojo.declare("dojox.widget.ColorPicker",
  23. dijit.form._FormWidget,
  24. {
  25. // summary: a HSV color picker - similar to Photoshop picker
  26. //
  27. // description:
  28. // Provides an interactive HSV ColorPicker similar to
  29. // PhotoShop's color selction tool. This is an enhanced
  30. // version of the default dijit.ColorPalette, though provides
  31. // no accessibility.
  32. //
  33. // example:
  34. // | var picker = new dojox.widget.ColorPicker({
  35. // | // a couple of example toggles:
  36. // | animatePoint:false,
  37. // | showHsv: false,
  38. // | webSafe: false,
  39. // | showRgb: false
  40. // | });
  41. //
  42. // example:
  43. // | <!-- markup: -->
  44. // | <div dojoType="dojox.widget.ColorPicker"></div>
  45. //
  46. // showRgb: Boolean
  47. // show/update RGB input nodes
  48. showRgb: true,
  49. // showHsv: Boolean
  50. // show/update HSV input nodes
  51. showHsv: true,
  52. // showHex: Boolean
  53. // show/update Hex value field
  54. showHex: true,
  55. // webSafe: Boolean
  56. // deprecated? or just use a toggle to show/hide that node, too?
  57. webSafe: true,
  58. // animatePoint: Boolean
  59. // toggle to use slideTo (true) or just place the cursor (false) on click
  60. animatePoint: true,
  61. // slideDuration: Integer
  62. // time in ms picker node will slide to next location (non-dragging) when animatePoint=true
  63. slideDuration: 250,
  64. // liveUpdate: Boolean
  65. // Set to true to fire onChange in an indeterminate way
  66. liveUpdate: false,
  67. // PICKER_HUE_H: int
  68. // Height of the hue picker, used to calculate positions
  69. PICKER_HUE_H: 150,
  70. // PICKER_SAT_VAL_H: int
  71. // Height of the 2d picker, used to calculate positions
  72. PICKER_SAT_VAL_H: 150,
  73. // PICKER_SAT_VAL_W: int
  74. // Width of the 2d picker, used to calculate positions
  75. PICKER_SAT_VAL_W: 150,
  76. // PICKER_HUE_SELECTOR_H: int
  77. // Height of the hue selector DOM node, used to calc offsets so that selection
  78. // is center of the image node.
  79. PICKER_HUE_SELECTOR_H: 8,
  80. // PICKER_SAT_SELECTOR_H: int
  81. // Height of the saturation selector DOM node, used to calc offsets so that selection
  82. // is center of the image node.
  83. PICKER_SAT_SELECTOR_H: 10,
  84. // PICKER_SAT_SELECTOR_W: int
  85. // Width of the saturation selector DOM node, used to calc offsets so that selection
  86. // is center of the image node.
  87. PICKER_SAT_SELECTOR_W: 10,
  88. // value: String
  89. // Default color for this component. Only hex values are accepted as incoming/returned
  90. // values. Adjust this value with `.attr`, eg: dijit.byId("myPicker").attr("value", "#ededed");
  91. // to cause the points to adjust and the values to reflect the current color.
  92. value: "#ffffff",
  93. _underlay: d.moduleUrl("dojox.widget","ColorPicker/images/underlay.png"),
  94. _hueUnderlay: d.moduleUrl("dojox.widget","ColorPicker/images/hue.png"),
  95. _pickerPointer: d.moduleUrl("dojox.widget","ColorPicker/images/pickerPointer.png"),
  96. _huePickerPointer: d.moduleUrl("dojox.widget","ColorPicker/images/hueHandle.png"),
  97. _huePickerPointerAlly: d.moduleUrl("dojox.widget","ColorPicker/images/hueHandleA11y.png"),
  98. // don't change to d.moduleUrl, build won't intern it.
  99. templateString: dojo.cache("dojox.widget", "ColorPicker/ColorPicker.html", "<table class=\"dojoxColorPicker\" dojoAttachEvent=\"onkeypress: _handleKey\" cellpadding=\"0\" cellspacing=\"0\">\n\t<tr>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxColorPickerBox\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" title=\"${saturationPickerTitle}\" alt=\"${saturationPickerTitle}\" class=\"dojoxColorPickerPoint\" src=\"${_pickerPointer}\" tabIndex=\"0\" dojoAttachPoint=\"cursorNode\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<img role=\"presentation\" alt=\"\" dojoAttachPoint=\"colorUnderlay\" dojoAttachEvent=\"onclick: _setPoint, onmousedown: _stopDrag\" class=\"dojoxColorPickerUnderlay\" src=\"${_underlay}\" ondragstart=\"return false\">\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxHuePicker\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" dojoAttachPoint=\"hueCursorNode\" tabIndex=\"0\" class=\"dojoxHuePickerPoint\" title=\"${huePickerTitle}\" alt=\"${huePickerTitle}\" src=\"${_huePickerPointer}\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<div class=\"dojoxHuePickerUnderlay\" dojoAttachPoint=\"hueNode\">\n\t\t\t\t <img role=\"presentation\" alt=\"\" dojoAttachEvent=\"onclick: _setHuePoint, onmousedown: _stopDrag\" src=\"${_hueUnderlay}\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\">\n\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerPreviewContainer\">\n\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"previewNode\" class=\"dojoxColorPickerPreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td valign=\"top\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"safePreviewNode\" class=\"dojoxColorPickerWebSafePreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"bottom\">\n\t\t\t\t\t\t<table class=\"dojoxColorPickerOptional\" cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerRgb\" dojoAttachPoint=\"rgbNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_r\">${redLabel}</label></td><td><input id=\"${_uId}_r\" dojoAttachPoint=\"Rval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_g\">${greenLabel}</label></td><td><input id=\"${_uId}_g\" dojoAttachPoint=\"Gval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_b\">${blueLabel}</label></td><td><input id=\"${_uId}_b\" dojoAttachPoint=\"Bval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerHsv\" dojoAttachPoint=\"hsvNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_h\">${hueLabel}</label></td><td><input id=\"${_uId}_h\" dojoAttachPoint=\"Hval\"size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${degLabel}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_s\">${saturationLabel}</label></td><td><input id=\"${_uId}_s\" dojoAttachPoint=\"Sval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_v\">${valueLabel}</label></td><td><input id=\"${_uId}_v\" dojoAttachPoint=\"Vval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td colspan=\"2\">\n\t\t\t\t\t\t\t\t\t<div class=\"dojoxColorPickerHex\" dojoAttachPoint=\"hexNode\" aria-live=\"polite\">\t\n\t\t\t\t\t\t\t\t\t\t<label for=\"${_uId}_hex\">&nbsp;${hexLabel}&nbsp;</label><input id=\"${_uId}_hex\" dojoAttachPoint=\"hexCode, focusNode, valueNode\" size=\"6\" class=\"dojoxColorPickerHexCode\" dojoAttachEvent=\"onchange: _colorInputChange\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</td>\n\t</tr>\n</table>\n\n"),
  100. postMixInProperties: function(){
  101. if(dojo.hasClass(dojo.body(), "dijit_a11y")){
  102. // Use the pointer that will show up in high contrast.
  103. this._huePickerPointer = this._huePickerPointerAlly;
  104. }
  105. this._uId = dijit.getUniqueId(this.id);
  106. dojo.mixin(this, dojo.i18n.getLocalization("dojox.widget", "ColorPicker"));
  107. dojo.mixin(this, dojo.i18n.getLocalization("dojo.cldr", "number"));
  108. this.inherited(arguments);
  109. },
  110. postCreate: function(){
  111. // summary:
  112. // As quickly as we can, set up ie6 alpha-filter support for our
  113. // underlay. we don't do image handles (done in css), just the 'core'
  114. // of this widget: the underlay.
  115. this.inherited(arguments);
  116. if(d.isIE < 7){
  117. this.colorUnderlay.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this._underlay+"', sizingMethod='scale')";
  118. this.colorUnderlay.src = this._blankGif.toString();
  119. }
  120. // hide toggle-able nodes:
  121. if(!this.showRgb){ this.rgbNode.style.visibility = "hidden"; }
  122. if(!this.showHsv){ this.hsvNode.style.visibility = "hidden"; }
  123. if(!this.showHex){ this.hexNode.style.visibility = "hidden"; }
  124. if(!this.webSafe){ this.safePreviewNode.style.visibility = "hidden"; }
  125. },
  126. startup: function(){
  127. if(this._started){
  128. return;
  129. }
  130. this._started = true;
  131. this.set("value", this.value);
  132. this._mover = new d.dnd.move.boxConstrainedMoveable(this.cursorNode, {
  133. box: {
  134. t: -(this.PICKER_SAT_SELECTOR_H/2),
  135. l: -(this.PICKER_SAT_SELECTOR_W/2),
  136. w:this.PICKER_SAT_VAL_W,
  137. h:this.PICKER_SAT_VAL_H
  138. }
  139. });
  140. this._hueMover = new d.dnd.move.boxConstrainedMoveable(this.hueCursorNode, {
  141. box: {
  142. t: -(this.PICKER_HUE_SELECTOR_H/2),
  143. l:0,
  144. w:0,
  145. h:this.PICKER_HUE_H
  146. }
  147. });
  148. this._subs = [];
  149. // no dnd/move/move published ... use a timer:
  150. this._subs.push(d.subscribe("/dnd/move/stop", d.hitch(this, "_clearTimer")));
  151. this._subs.push(d.subscribe("/dnd/move/start", d.hitch(this, "_setTimer")));
  152. // Bind to up, down, left and right arrows on the hue and saturation nodes.
  153. this._keyListeners = [];
  154. this._connects.push(dijit.typematic.addKeyListener(this.hueCursorNode,{
  155. charOrCode: dojo.keys.UP_ARROW,
  156. shiftKey: false,
  157. metaKey: false,
  158. ctrlKey: false,
  159. altKey: false
  160. }, this, dojo.hitch(this, this._updateHueCursorNode), 25, 25));
  161. this._connects.push(dijit.typematic.addKeyListener(this.hueCursorNode,{
  162. charOrCode: dojo.keys.DOWN_ARROW,
  163. shiftKey: false,
  164. metaKey: false,
  165. ctrlKey: false,
  166. altKey: false
  167. }, this, dojo.hitch(this, this._updateHueCursorNode), 25, 25));
  168. this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
  169. charOrCode: dojo.keys.UP_ARROW,
  170. shiftKey: false,
  171. metaKey: false,
  172. ctrlKey: false,
  173. altKey: false
  174. }, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
  175. this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
  176. charOrCode: dojo.keys.DOWN_ARROW,
  177. shiftKey: false,
  178. metaKey: false,
  179. ctrlKey: false,
  180. altKey: false
  181. }, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
  182. this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
  183. charOrCode: dojo.keys.LEFT_ARROW,
  184. shiftKey: false,
  185. metaKey: false,
  186. ctrlKey: false,
  187. altKey: false
  188. }, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
  189. this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
  190. charOrCode: dojo.keys.RIGHT_ARROW,
  191. shiftKey: false,
  192. metaKey: false,
  193. ctrlKey: false,
  194. altKey: false
  195. }, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
  196. },
  197. _setValueAttr: function(value){
  198. if(!this._started){ return; }
  199. this.setColor(value, true);
  200. },
  201. setColor: function(/* String */color, force){
  202. // summary: Set a color on a picker. Usually used to set
  203. // initial color as an alternative to passing defaultColor option
  204. // to the constructor.
  205. var col = dojox.color.fromString(color);
  206. this._updatePickerLocations(col);
  207. this._updateColorInputs(col);
  208. this._updateValue(col, force);
  209. },
  210. _setTimer: function(/* d.dnd.Mover */mover){
  211. // FIXME: should I assume this? focus on mouse down so on mouse up
  212. dijit.focus(mover.node);
  213. d.setSelectable(this.domNode,false);
  214. this._timer = setInterval(d.hitch(this, "_updateColor"), 45);
  215. },
  216. _clearTimer: function(/* d.dnd.Mover */mover){
  217. clearInterval(this._timer);
  218. this._timer = null;
  219. this.onChange(this.value);
  220. d.setSelectable(this.domNode,true);
  221. },
  222. _setHue: function(/* Decimal */h){
  223. // summary:
  224. // Sets a natural color background for the
  225. // underlay image against closest hue value (full saturation)
  226. // h: 0..360
  227. d.style(this.colorUnderlay, "backgroundColor", dojox.color.fromHsv(h,100,100).toHex());
  228. },
  229. _updateHueCursorNode: function(count, node, e){
  230. // summary:
  231. // Function used by the typematic code to handle cursor position and update
  232. // via keyboard.
  233. // count:
  234. // -1 means stop, anything else is just how many times it was called.
  235. // node:
  236. // The node generating the event.
  237. // e:
  238. // The event.
  239. if(count !== -1){
  240. var y = dojo.style(this.hueCursorNode, "top");
  241. var selCenter = (this.PICKER_HUE_SELECTOR_H/2);
  242. // Account for our offset
  243. y += selCenter;
  244. var update = false;
  245. if(e.charOrCode == dojo.keys.UP_ARROW){
  246. if(y > 0){
  247. y -= 1;
  248. update = true;
  249. }
  250. }else if(e.charOrCode == dojo.keys.DOWN_ARROW){
  251. if(y < this.PICKER_HUE_H){
  252. y += 1;
  253. update = true;
  254. }
  255. }
  256. y -= selCenter;
  257. if(update){
  258. dojo.style(this.hueCursorNode, "top", y + "px");
  259. }
  260. }else{
  261. this._updateColor(true);
  262. }
  263. },
  264. _updateCursorNode: function(count, node, e){
  265. // summary:
  266. // Function used by the typematic code to handle cursor position and update
  267. // via keyboard.
  268. // count:
  269. // -1 means stop, anything else is just how many times it was called.
  270. // node:
  271. // The node generating the event.
  272. // e:
  273. // The event.
  274. var selCenterH = this.PICKER_SAT_SELECTOR_H/2;
  275. var selCenterW = this.PICKER_SAT_SELECTOR_W/2;
  276. if(count !== -1){
  277. var y = dojo.style(this.cursorNode, "top");
  278. var x = dojo.style(this.cursorNode, "left");
  279. // Account for our offsets to center
  280. y += selCenterH;
  281. x += selCenterW;
  282. var update = false;
  283. if(e.charOrCode == dojo.keys.UP_ARROW){
  284. if(y > 0){
  285. y -= 1;
  286. update = true;
  287. }
  288. }else if(e.charOrCode == dojo.keys.DOWN_ARROW){
  289. if(y < this.PICKER_SAT_VAL_H){
  290. y += 1;
  291. update = true;
  292. }
  293. }else if(e.charOrCode == dojo.keys.LEFT_ARROW){
  294. if(x > 0){
  295. x -= 1;
  296. update = true;
  297. }
  298. }else if(e.charOrCode == dojo.keys.RIGHT_ARROW){
  299. if(x < this.PICKER_SAT_VAL_W){
  300. x += 1;
  301. update = true;
  302. }
  303. }
  304. if(update){
  305. // Account for our offsets to center
  306. y -= selCenterH;
  307. x -= selCenterW;
  308. dojo.style(this.cursorNode, "top", y + "px");
  309. dojo.style(this.cursorNode, "left", x + "px");
  310. }
  311. }else{
  312. this._updateColor(true);
  313. }
  314. },
  315. _updateColor: function(){
  316. // summary: update the previewNode color, and input values [optional]
  317. var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2,
  318. satSelCenterH = this.PICKER_SAT_SELECTOR_H/2,
  319. satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
  320. var _huetop = d.style(this.hueCursorNode,"top") + hueSelCenter,
  321. _pickertop = d.style(this.cursorNode,"top") + satSelCenterH,
  322. _pickerleft = d.style(this.cursorNode,"left") + satSelCenterW,
  323. h = Math.round(360 - (_huetop / this.PICKER_HUE_H * 360)),
  324. col = dojox.color.fromHsv(h, _pickerleft / this.PICKER_SAT_VAL_W * 100, 100 - (_pickertop / this.PICKER_SAT_VAL_H * 100))
  325. ;
  326. this._updateColorInputs(col);
  327. this._updateValue(col, true);
  328. // update hue, not all the pickers
  329. if (h!=this._hue) {
  330. this._setHue(h);
  331. }
  332. },
  333. _colorInputChange: function(e){
  334. //summary: updates picker position and inputs
  335. // according to rgb, hex or hsv input changes
  336. var col, hasit = false;
  337. switch (e.target) {
  338. //transform to hsv to pixels
  339. case this.hexCode:
  340. col = dojox.color.fromString(e.target.value);
  341. hasit = true;
  342. break;
  343. case this.Rval:
  344. case this.Gval:
  345. case this.Bval:
  346. col = dojox.color.fromArray([this.Rval.value, this.Gval.value, this.Bval.value]);
  347. hasit = true;
  348. break;
  349. case this.Hval:
  350. case this.Sval:
  351. case this.Vval:
  352. col = dojox.color.fromHsv(this.Hval.value, this.Sval.value, this.Vval.value);
  353. hasit = true;
  354. break;
  355. }
  356. if(hasit){
  357. this._updatePickerLocations(col);
  358. this._updateColorInputs(col);
  359. this._updateValue(col, true);
  360. }
  361. },
  362. _updateValue: function(/* dojox.color.Color */col, /* Boolean */fireChange){
  363. // summary: updates the value of the widget
  364. // can cancel reverse onChange by specifying second param
  365. var hex = col.toHex();
  366. this.value = this.valueNode.value = hex;
  367. // anytime we muck with the color, fire onChange?
  368. if(fireChange && (!this._timer || this.liveUpdate)) {
  369. this.onChange(hex);
  370. }
  371. },
  372. _updatePickerLocations: function(/* dojox.color.Color */col){
  373. //summary: update handles on the pickers acording to color values
  374. //
  375. var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2,
  376. satSelCenterH = this.PICKER_SAT_SELECTOR_H/2,
  377. satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
  378. var hsv = col.toHsv(),
  379. ypos = Math.round(this.PICKER_HUE_H - hsv.h / 360 * this.PICKER_HUE_H) - hueSelCenter,
  380. newLeft = Math.round(hsv.s / 100 * this.PICKER_SAT_VAL_W) - satSelCenterW,
  381. newTop = Math.round(this.PICKER_SAT_VAL_H - hsv.v / 100 * this.PICKER_SAT_VAL_H) - satSelCenterH
  382. ;
  383. if (this.animatePoint) {
  384. d.fx.slideTo({
  385. node: this.hueCursorNode,
  386. duration: this.slideDuration,
  387. top: ypos,
  388. left: 0
  389. }).play();
  390. d.fx.slideTo({
  391. node: this.cursorNode,
  392. duration: this.slideDuration,
  393. top: newTop,
  394. left: newLeft
  395. }).play();
  396. }
  397. else {
  398. d.style(this.hueCursorNode, "top", ypos + "px");
  399. d.style(this.cursorNode, {
  400. left: newLeft + "px",
  401. top: newTop + "px"
  402. });
  403. }
  404. // limit hue calculations to only when it changes
  405. if (hsv.h != this._hue) {
  406. this._setHue(hsv.h);
  407. }
  408. },
  409. _updateColorInputs: function(/* dojox.color.Color */col){
  410. //summary: updates color inputs that were changed through other inputs
  411. //or by clicking on the picker
  412. var hex = col.toHex();
  413. if (this.showRgb) {
  414. this.Rval.value = col.r;
  415. this.Gval.value = col.g;
  416. this.Bval.value = col.b;
  417. }
  418. if (this.showHsv) {
  419. var hsv = col.toHsv();
  420. this.Hval.value = Math.round((hsv.h)); // convert to 0..360
  421. this.Sval.value = Math.round(hsv.s);
  422. this.Vval.value = Math.round(hsv.v);
  423. }
  424. if (this.showHex) {
  425. this.hexCode.value = hex;
  426. }
  427. this.previewNode.style.backgroundColor = hex;
  428. if (this.webSafe) {
  429. this.safePreviewNode.style.backgroundColor = webSafeFromHex(hex);
  430. }
  431. },
  432. _setHuePoint: function(/* Event */evt){
  433. // summary: set the hue picker handle on relative y coordinates
  434. var selCenter = (this.PICKER_HUE_SELECTOR_H/2);
  435. var ypos = evt.layerY - selCenter;
  436. if(this.animatePoint){
  437. d.fx.slideTo({
  438. node: this.hueCursorNode,
  439. duration:this.slideDuration,
  440. top: ypos,
  441. left: 0,
  442. onEnd: d.hitch(this, function() {this._updateColor(true); dijit.focus(this.hueCursorNode);})
  443. }).play();
  444. }else{
  445. d.style(this.hueCursorNode, "top", ypos + "px");
  446. this._updateColor(false);
  447. }
  448. },
  449. _setPoint: function(/* Event */evt){
  450. // summary: set our picker point based on relative x/y coordinates
  451. // evt.preventDefault();
  452. var satSelCenterH = this.PICKER_SAT_SELECTOR_H/2;
  453. var satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
  454. var newTop = evt.layerY - satSelCenterH;
  455. var newLeft = evt.layerX - satSelCenterW;
  456. if(evt){ dijit.focus(evt.target); }
  457. if(this.animatePoint){
  458. d.fx.slideTo({
  459. node: this.cursorNode,
  460. duration: this.slideDuration,
  461. top: newTop,
  462. left: newLeft,
  463. onEnd: d.hitch(this, function() {this._updateColor(true); dijit.focus(this.cursorNode);})
  464. }).play();
  465. }else{
  466. d.style(this.cursorNode, {
  467. left: newLeft + "px",
  468. top: newTop + "px"
  469. });
  470. this._updateColor(false);
  471. }
  472. },
  473. _handleKey: function(/* Event */e){
  474. // FIXME: not implemented YET
  475. // var keys = d.keys;
  476. },
  477. focus: function(){
  478. // summary:
  479. // Put focus on this widget, only if focus isn't set on it already.
  480. if(!this._focused){
  481. dijit.focus(this.focusNode);
  482. }
  483. },
  484. _stopDrag: function(e){
  485. // summary:
  486. // Function to hald the mouse down default
  487. // to disable draggong of images out of the color
  488. // picker.
  489. dojo.stopEvent(e);
  490. },
  491. destroy: function(){
  492. // summary:
  493. // Over-ride to clean up subscriptions, etc.
  494. this.inherited(arguments);
  495. dojo.forEach(this._subs, function(sub){
  496. dojo.unsubscribe(sub);
  497. });
  498. delete this._subs;
  499. }
  500. });
  501. })(dojo);
  502. }