5ece840f3be9ab26a67b90fbd47dc78f9bad2fae.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. if (!dojo._hasResource["dojox.widget.ColorPicker"]) { // _hasResource checks
  2. // added by build. Do
  3. // not use _hasResource
  4. // directly in your
  5. // code.
  6. dojo._hasResource["dojox.widget.ColorPicker"] = true;
  7. dojo.provide("dojox.widget.ColorPicker");
  8. dojo.experimental("dojox.widget.ColorPicker"); // level: prototype
  9. dojo.require("dijit.form._FormWidget");
  10. dojo.require("dojo.dnd.move");
  11. dojo.require("dojo.fx");
  12. dojo.declare("dojox.widget.ColorPicker", dijit.form._FormWidget, {
  13. // summary: a HSV color picker - like PhotoShop
  14. //
  15. // description:
  16. // provides an interactive HSV ColorPicker similar to
  17. // PhotoShop's color selction tool. Will eventually
  18. // mixin FormWidget and be used as a suplement or a
  19. // 'more interactive' replacement for ColorPalette
  20. //
  21. // example:
  22. //
  23. // code:
  24. // var picker = new dojox.widget.ColorPicker({
  25. // // a couple of example toggles:
  26. // animatePoint:false,
  27. // showHsv: false,
  28. // webSafe: false,
  29. // showRgb: false
  30. // });
  31. //
  32. // markup:
  33. // <div dojoType="dojox.widget.ColorPicker"></div>
  34. //
  35. // showRgb: Boolean
  36. // show/update RGB input nodes
  37. showRgb : true,
  38. // showHsv: Boolean
  39. // show/update HSV input nodes
  40. showHsv : true,
  41. // showHex: Boolean
  42. // show/update Hex value field
  43. showHex : true,
  44. // webSafe: Boolean
  45. // deprecated? or just use a toggle to show/hide that node, too?
  46. webSafe : true,
  47. // animatePoint: Boolean
  48. // toggle to use slideTo (true) or just place the cursor (false) on
  49. // click
  50. animatePoint : true,
  51. // slideDuration: Integer
  52. // time in ms picker node will slide to next location (non-dragging)
  53. // when animatePoint=true
  54. slideDuration : 250,
  55. _underlay : dojo.moduleUrl("dojox.widget",
  56. "ColorPicker/images/underlay.png"),
  57. templateString : "<div class=\"dojoxColorPicker\">\n\t<div class=\"dojoxColorPickerBox\">\n\t\t<div dojoAttachPoint=\"cursorNode\" class=\"dojoxColorPickerPoint\"></div>\n\t\t<img dojoAttachPoint=\"colorUnderlay\" dojoAttachEvent=\"onclick: _setPoint\" class=\"dojoxColorPickerUnderlay\" src=\"${_underlay}\">\n\t</div>\n\t<div class=\"dojoxHuePicker\">\n\t\t<div dojoAttachPoint=\"hueCursorNode\" class=\"dojoxHuePickerPoint\"></div>\n\t\t<div dojoAttachPoint=\"hueNode\" class=\"dojoxHuePickerUnderlay\" dojoAttachEvent=\"onclick: _setHuePoint\"></div>\n\t</div>\n\t<div dojoAttachPoint=\"previewNode\" class=\"dojoxColorPickerPreview\"></div>\n\t<div dojoAttachPoint=\"safePreviewNode\" class=\"dojoxColorPickerWebSafePreview\"></div>\n\t<div class=\"dojoxColorPickerOptional\">\n\t\t<div class=\"dijitInline dojoxColorPickerRgb\" dojoAttachPoint=\"rgbNode\">\n\t\t\t<table>\n\t\t\t<tr><td>r</td><td><input dojoAttachPoint=\"Rval\" size=\"1\"></td></tr>\n\t\t\t<tr><td>g</td><td><input dojoAttachPoint=\"Gval\" size=\"1\"></td></tr>\n\t\t\t<tr><td>b</td><td><input dojoAttachPoint=\"Bval\" size=\"1\"></td></tr>\n\t\t\t</table>\n\t\t</div>\n\t\t<div class=\"dijitInline dojoxColorPickerHsv\" dojoAttachPoint=\"hsvNode\">\n\t\t\t<table>\n\t\t\t<tr><td>h</td><td><input dojoAttachPoint=\"Hval\"size=\"1\"> &deg;</td></tr>\n\t\t\t<tr><td>s</td><td><input dojoAttachPoint=\"Sval\" size=\"1\"> %</td></tr>\n\t\t\t<tr><td>v</td><td><input dojoAttachPoint=\"Vval\" size=\"1\"> %</td></tr>\n\t\t\t</table>\n\t\t</div>\n\t\t<div class=\"dojoxColorPickerHex\" dojoAttachPoint=\"hexNode\">\t\n\t\t\thex: <input dojoAttachPoint=\"hexCode, focusNode\" size=\"6\" class=\"dojoxColorPickerHexCode\">\n\t\t</div>\n\t</div>\n</div>\n",
  58. postCreate : function() {
  59. // summary: As quickly as we can, set up ie6 alpha-filter support
  60. // for our
  61. // underlay. we don't do image handles (done in css), just the
  62. // 'core'
  63. // of this widget: the underlay.
  64. if (dojo.isIE && dojo.isIE < 7) {
  65. this.colorUnderlay.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
  66. + this._underlay + "', sizingMethod='scale')";
  67. this.colorUnderlay.src = dojo.moduleUrl("dojox.widget",
  68. "FisheyeList/blank.gif").toString();
  69. }
  70. // hide toggle-able nodes:
  71. if (!this.showRgb) {
  72. this.rgbNode.style.display = "none";
  73. }
  74. if (!this.showHsv) {
  75. this.hsvNode.style.display = "none";
  76. }
  77. if (!this.showHex) {
  78. this.hexNode.style.display = "none";
  79. }
  80. if (!this.webSafe) {
  81. this.safePreviewNode.style.display = "none";
  82. }
  83. },
  84. startup : function() {
  85. // summary: defer all additional calls until we're started, and our
  86. // embeded sliders are loaded? (not implemented yet)
  87. // this._offset = ((dojo.marginBox(this.cursorNode).w)/2);
  88. this._offset = 0;
  89. this._mover = new dojo.dnd.Moveable(this.cursorNode, {
  90. mover : dojo.dnd.boxConstrainedMover({
  91. t : 0,
  92. l : 0,
  93. w : 150,
  94. h : 150
  95. })
  96. });
  97. this._hueMover = new dojo.dnd.Moveable(this.hueCursorNode, {
  98. mover : dojo.dnd.boxConstrainedMover({
  99. t : 0,
  100. l : 0,
  101. w : 0,
  102. h : 150
  103. })
  104. });
  105. // no dnd/move/move published ... use a timer:
  106. dojo.subscribe("/dnd/move/stop", dojo.hitch(this, "_clearTimer"));
  107. dojo.subscribe("/dnd/move/start", dojo.hitch(this, "_setTimer"));
  108. // ugly scaling calculator. need a XYslider badly
  109. this._sc = (1 / dojo.coords(this.colorUnderlay).w);
  110. this._hueSc = (255 / (dojo.coords(this.hueNode).h + this._offset));
  111. // initial color
  112. this._updateColor();
  113. },
  114. _setTimer : function(/* dojo.dnd.Mover */mover) {
  115. this._timer = setInterval(dojo.hitch(this, "_updateColor"), 45);
  116. },
  117. _clearTimer : function(/* dojo.dnd.Mover */mover) {
  118. clearInterval(this._timer);
  119. this.onChange(this.value);
  120. },
  121. _setHue : function(/* Decimal */h) {
  122. // summary: sets a natural color background for the
  123. // underlay image against closest hue value (full saturation)
  124. // h: 0..255
  125. // this is not a pretty conversion:
  126. var hue = dojo.colorFromArray(this._hsv2rgb(h, 1, 1, {
  127. inputRange : 1
  128. })).toHex();
  129. dojo.style(this.colorUnderlay, "backgroundColor", hue);
  130. },
  131. _updateColor : function() {
  132. // summary: update the previewNode color, and input values
  133. // [optional]
  134. var h = Math
  135. .round((255 + (this._offset))
  136. - ((dojo.style(this.hueCursorNode, "top") + this._offset) * this._hueSc));
  137. var s = Math.round((dojo.style(this.cursorNode, "left") * this._sc)
  138. * 100);
  139. var v = Math.round(100
  140. - (dojo.style(this.cursorNode, "top") * this._sc) * 100);
  141. // limit hue calculations to only when it changes
  142. if (h != this._hue) {
  143. this._setHue(h);
  144. }
  145. var rgb = this._hsv2rgb(h, s / 100, v / 100, {
  146. inputRange : 1
  147. });
  148. var hex = (dojo.colorFromArray(rgb).toHex());
  149. this.previewNode.style.backgroundColor = hex;
  150. if (this.webSafe) {
  151. this.safePreviewNode.style.backgroundColor = hex;
  152. }
  153. if (this.showHex) {
  154. this.hexCode.value = hex;
  155. }
  156. if (this.showRgb) {
  157. this.Rval.value = rgb[0];
  158. this.Gval.value = rgb[1];
  159. this.Bval.value = rgb[2];
  160. }
  161. if (this.showHsv) {
  162. this.Hval.value = Math.round((h * 360) / 255); // convert to
  163. // 0..360
  164. this.Sval.value = s;
  165. this.Vval.value = v;
  166. }
  167. this.value = hex;
  168. // anytime we muck with the color, fire onChange?
  169. if (!this._timer && !(arguments[1])) {
  170. this.setValue(this.value);
  171. this.onChange(this.value);
  172. }
  173. },
  174. _setHuePoint : function(/* Event */evt) {
  175. // summary: set the hue picker handle on relative y coordinates
  176. if (this.animatePoint) {
  177. dojo.fx.slideTo({
  178. node : this.hueCursorNode,
  179. duration : this.slideDuration,
  180. top : evt.layerY,
  181. left : 0,
  182. onEnd : dojo.hitch(this, "_updateColor")
  183. }).play();
  184. } else {
  185. dojo.style(this.hueCursorNode, "top", (evt.layerY) + "px");
  186. this._updateColor(false);
  187. }
  188. },
  189. _setPoint : function(/* Event */evt) {
  190. // summary: set our picker point based on relative x/y coordinates
  191. if (this.animatePoint) {
  192. dojo.fx.slideTo({
  193. node : this.cursorNode,
  194. duration : this.slideDuration,
  195. top : evt.layerY - this._offset,
  196. left : evt.layerX - this._offset,
  197. onEnd : dojo.hitch(this, "_updateColor")
  198. }).play();
  199. } else {
  200. dojo.style(this.cursorNode, "left", (evt.layerX - this._offset)
  201. + "px");
  202. dojo.style(this.cursorNode, "top", (evt.layerY - this._offset)
  203. + "px");
  204. this._updateColor(false);
  205. }
  206. },
  207. // this ported directly from 0.4 dojo.gfx.colors.hsv, with bugs :)
  208. // FIXME: use ttrenka's HSB ?
  209. _hsv2rgb : function(/* int || Array */h, /* int */s, /* int */v, /* Object? */
  210. options) {
  211. // summary
  212. // converts an HSV value set to RGB, ranges depending on optional
  213. // options object.
  214. // patch for options by Matthew Eernisse
  215. if (dojo.isArray(h)) {
  216. if (s) {
  217. options = s;
  218. }
  219. v = h[2] || 0;
  220. s = h[1] || 0;
  221. h = h[0] || 0;
  222. }
  223. var opt = {
  224. inputRange : (options && options.inputRange)
  225. ? options.inputRange
  226. : [255, 255, 255],
  227. outputRange : (options && options.outputRange)
  228. ? options.outputRange
  229. : 255
  230. };
  231. switch (opt.inputRange[0]) {
  232. // 0.0-1.0
  233. case 1 :
  234. h = h * 360;
  235. break;
  236. // 0-100
  237. case 100 :
  238. h = (h / 100) * 360;
  239. break;
  240. // 0-360
  241. case 360 :
  242. h = h;
  243. break;
  244. // 0-255
  245. default :
  246. h = (h / 255) * 360;
  247. }
  248. if (h == 360) {
  249. h = 0;
  250. }
  251. // no need to alter if inputRange[1] = 1
  252. switch (opt.inputRange[1]) {
  253. case 100 :
  254. s /= 100;
  255. break;
  256. case 255 :
  257. s /= 255;
  258. }
  259. // no need to alter if inputRange[1] = 1
  260. switch (opt.inputRange[2]) {
  261. case 100 :
  262. v /= 100;
  263. break;
  264. case 255 :
  265. v /= 255;
  266. }
  267. var r = null;
  268. var g = null;
  269. var b = null;
  270. if (s == 0) {
  271. // color is on black-and-white center line
  272. // achromatic: shades of gray
  273. r = v;
  274. g = v;
  275. b = v;
  276. } else {
  277. // chromatic color
  278. var hTemp = h / 60; // h is now IN [0,6]
  279. var i = Math.floor(hTemp); // largest integer <= h
  280. var f = hTemp - i; // fractional part of h
  281. var p = v * (1 - s);
  282. var q = v * (1 - (s * f));
  283. var t = v * (1 - (s * (1 - f)));
  284. switch (i) {
  285. case 0 :
  286. r = v;
  287. g = t;
  288. b = p;
  289. break;
  290. case 1 :
  291. r = q;
  292. g = v;
  293. b = p;
  294. break;
  295. case 2 :
  296. r = p;
  297. g = v;
  298. b = t;
  299. break;
  300. case 3 :
  301. r = p;
  302. g = q;
  303. b = v;
  304. break;
  305. case 4 :
  306. r = t;
  307. g = p;
  308. b = v;
  309. break;
  310. case 5 :
  311. r = v;
  312. g = p;
  313. b = q;
  314. break;
  315. }
  316. }
  317. switch (opt.outputRange) {
  318. case 1 :
  319. r = dojo.math.round(r, 2);
  320. g = dojo.math.round(g, 2);
  321. b = dojo.math.round(b, 2);
  322. break;
  323. case 100 :
  324. r = Math.round(r * 100);
  325. g = Math.round(g * 100);
  326. b = Math.round(b * 100);
  327. break;
  328. default :
  329. r = Math.round(r * 255);
  330. g = Math.round(g * 255);
  331. b = Math.round(b * 255);
  332. }
  333. return [r, g, b];
  334. }
  335. });
  336. }