PageRenderTime 65ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/ample/languages/xul/elements/colorpicker-pane.js

https://github.com/marsch/amplesdk
JavaScript | 289 lines | 223 code | 45 blank | 21 comment | 23 complexity | 0d9b9588424eda1db9722d89e7f014cc MD5 | raw file
  1. /*
  2. * Ample SDK - JavaScript GUI Framework
  3. *
  4. * Copyright (c) 2009 Sergey Ilinsky
  5. * Dual licensed under the MIT and GPL licenses.
  6. * See: http://www.amplesdk.com/about/licensing/
  7. *
  8. */
  9. var cXULElement_colorpicker_pane = function() {
  10. // Private Properties
  11. this.x = 0;
  12. this.y = 0;
  13. this.b = 1;
  14. };
  15. cXULElement_colorpicker_pane.prototype = new cXULPopupElement("colorpicker-pane");
  16. cXULElement_colorpicker_pane.attributes = {};
  17. cXULElement_colorpicker_pane.attributes.value = "#FF0000";
  18. // Public Method
  19. // Private Methods
  20. cXULElement_colorpicker_pane.prototype._moveTo = function(sName, oPosition) {
  21. if (oPosition.x)
  22. this.$getContainer(sName).style.left = oPosition.x + "px";
  23. if (oPosition.y)
  24. this.$getContainer(sName).style.top = oPosition.y + "px";
  25. };
  26. cXULElement_colorpicker_pane.prototype._setColor = function(sColor) {
  27. var oColor;
  28. if (oColor = cXULElement_colorpicker_pane._RGBtoXYB(sColor)) {
  29. this.b = oColor.b;
  30. this.x = oColor.x;
  31. this.y = oColor.y;
  32. this._moveTo('palette-pointer', {'x' : this.x - 9, 'y' : this.y - 9});
  33. this.$getContainer('color').style.backgroundColor = sColor;
  34. this._setColorBrightness(cXULElement_colorpicker_pane._XYBtoRGB({'x': this.x, 'y': this.y, 'b': 0}));
  35. this._setPaletteBrightness(this.b);
  36. this._moveTo('brightness-pointer', {'y' : this.b * 255 - 2});
  37. }
  38. };
  39. cXULElement_colorpicker_pane.prototype._setColorBrightness = function(sColor) {
  40. this.$getContainer('brightness').style.backgroundColor = sColor;
  41. this.$getContainer('brightness-shader').style.filter = "progid:DXImageTransform.Microsoft.Gradient(startColorStr='" + sColor + "', endColorStr='#000000', gradientType='0');";
  42. };
  43. cXULElement_colorpicker_pane.prototype._setPaletteBrightness = function(nBrightness) {
  44. // applying styles
  45. var oElementDOM = this.$getContainer('palette-shader');
  46. oElementDOM.style.filter = 'progid:DXImageTransform.Microsoft.alpha(opacity=' + nBrightness * 100 + ')'; // IE
  47. oElementDOM.style.opacity = nBrightness; // Safari|FF1.5 (CSS 3)
  48. oElementDOM.style.MozOpacity = nBrightness; // mozilla
  49. };
  50. cXULElement_colorpicker_pane.prototype._getComputedStyleByEvent = function(oEvent, sName) {
  51. var oPosition = this.getBoundingClientRect(sName);
  52. var nPositionX = oEvent.clientX - oPosition.left/* + oPosition.scrollLeft*/;
  53. var nPositionY = oEvent.clientY - oPosition.top/* + oPosition.scrollTop*/;
  54. // limit value by the range (0..255)
  55. nPositionX = nPositionX < 0 ? 0 :(nPositionX > 255 ? 255 : nPositionX);
  56. nPositionY = nPositionY < 0 ? 0 :(nPositionY > 255 ? 255 : nPositionY);
  57. return {'x' : nPositionX, 'y': nPositionY};
  58. };
  59. cXULElement_colorpicker_pane.prototype._setColorValue = function(sColor) {
  60. this.$getContainer('color').style.backgroundColor = sColor;
  61. this.$getContainer('value').value = sColor;
  62. };
  63. cXULElement_colorpicker_pane.prototype._detachHandlers = function() {
  64. document.onmousemove = null;
  65. document.onmouseup = null;
  66. };
  67. // Event handlers
  68. cXULElement_colorpicker_pane.prototype._onInputChange = function(oEvent, sValue) {
  69. this._setColor(sValue);
  70. };
  71. cXULElement_colorpicker_pane.prototype._onPointersBrightnessMouseMove = function(oEvent) {
  72. var oPosition = this._getComputedStyleByEvent(oEvent, 'brightness');
  73. this._moveTo('brightness-pointer', {'y' : oPosition.y - 3});
  74. this.b = Math.round(100 * oPosition.y / 255) / 100;
  75. this._setPaletteBrightness(this.b);
  76. this._setColorValue(cXULElement_colorpicker_pane._XYBtoRGB({'x': this.x, 'y': this.y, 'b': this.b}));
  77. };
  78. cXULElement_colorpicker_pane.prototype._onPointersBrightnessMouseDown = function(oEvent) {
  79. var oElement = this;
  80. document.onmousemove = function(e) {
  81. return oElement._onPointersBrightnessMouseMove(e || event)
  82. };
  83. document.onmouseup = function() {
  84. oElement._detachHandlers();
  85. };
  86. this._onPointersBrightnessMouseMove(oEvent);
  87. };
  88. cXULElement_colorpicker_pane.prototype._onPointerPaletteMouseMove = function(oEvent) {
  89. var oPosition = this._getComputedStyleByEvent(oEvent, "palette");
  90. this.x = oPosition.x;
  91. this.y = oPosition.y;
  92. this._moveTo('palette-pointer', {'x' : this.x - 9, 'y' : this.y - 9});
  93. this._setColorBrightness(cXULElement_colorpicker_pane._XYBtoRGB({'x': this.x, 'y': this.y, 'b': 0}));
  94. this._setColorValue(cXULElement_colorpicker_pane._XYBtoRGB({'x': this.x, 'y': this.y, 'b': this.b}));
  95. };
  96. cXULElement_colorpicker_pane.prototype._onPointerPaletteMouseDown = function(oEvent) {
  97. var oElement = this;
  98. document.onmousemove = function(e) {
  99. return oElement._onPointerPaletteMouseMove(e || event)
  100. };
  101. document.onmouseup = function() {
  102. oElement._detachHandlers();
  103. };
  104. this._onPointerPaletteMouseMove(oEvent);
  105. };
  106. // Overrride dialog methods
  107. cXULElement_colorpicker_pane.prototype.acceptDialog = function() {
  108. this.attributes.value = this.$getContainer('value').value;
  109. // fire select event
  110. var oEvent = this.ownerDocument.createEvent("Event");
  111. oEvent.initEvent("accept", false, false);
  112. this.dispatchEvent(oEvent);
  113. };
  114. cXULElement_colorpicker_pane.prototype.cancelDialog = function() {
  115. this.setAttribute("value", this.attributes.value);
  116. // fire cancel event
  117. var oEvent = this.ownerDocument.createEvent("Event");
  118. oEvent.initEvent("cancel", false, false);
  119. this.dispatchEvent(oEvent);
  120. };
  121. // Class handlers
  122. cXULElement_colorpicker_pane.handlers = {
  123. "DOMAttrModified": function(oEvent) {
  124. if (oEvent.target == this) {
  125. switch (oEvent.attrName) {
  126. case "value":
  127. this._setColor(oEvent.newValue || '');
  128. this.$getContainer('value').value = oEvent.newValue || '';
  129. break;
  130. default:
  131. this.$mapAttribute(oEvent.attrName, oEvent.newValue);
  132. }
  133. }
  134. },
  135. "DOMNodeInsertedIntoDocument": function() {
  136. this._setColor(cXULElement_colorpicker_pane.attributes.value);
  137. }
  138. };
  139. // Render
  140. cXULElement_colorpicker_pane.prototype.$getTagOpen = function() {
  141. return '<div class="xul-colorpicker-pane xul-menupopup' + (this.hasAttribute("class") ? ' ' + this.getAttribute("class") : '') + '" style="' +
  142. (this.getAttribute("hidden") == "true" ? "display:none;" : '') +
  143. (this.hasAttribute("style") ? this.getAttribute("style") : '') + '">\
  144. <div class="xul-menupopup--shadow-right" style="position:absolute;"></div>\
  145. <div class="xul-menupopup--shadow-bottom" style="position:absolute;"></div>\
  146. <table cellpadding="0" cellspacing="0" border="0">\
  147. <tbody>\
  148. <tr>\
  149. <td valign="top">\
  150. <div class="xul-colorpicker-pane--palette" style="position:relative;" onmousedown="ample.$instance(this)._onPointerPaletteMouseDown(event)">\
  151. <div class="xul-colorpicker-pane--palette-shader"><br /></div>\
  152. <div class="xul-colorpicker-pane--palette-pointer" style="position:absolute;"><br /></div>\
  153. </div>\
  154. </td>\
  155. <td align="center" valign="top" style="position:relative;display:block;">\
  156. <div style="width:39px" onmousedown="ample.$instance(this)._onPointersBrightnessMouseDown(event);">\
  157. <div class="xul-colorpicker-pane--brightness">\
  158. <div class="xul-colorpicker-pane--brightness-shader"><br /></div>\
  159. </div>\
  160. <div class="xul-colorpicker-pane--brightness-pointer" style="position:absolute;left:1px;"><br /></div>\
  161. </div>\
  162. </td>\
  163. <td valign="top">\
  164. <table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%">\
  165. <tbody>\
  166. <tr><td align="right"><div class="xul-colorpicker-pane--color"></div></td></tr>\
  167. <tr><td><br /></td></tr>\
  168. <tr><td><input autocomplete="no" type="text" value="#FF0000" maxlength="7" class="xul-colorpicker-pane--value" onchange="ample.$instance(this)._onInputChange(event, this.value)" onkeyup="ample.$instance(this)._onInputChange(event, this.value)" onselectstart="event.cancelBubble=true;" oncontextmenu="event.cancelBubble=true"/></td></tr>\
  169. <tr><td><br /></td></tr>\
  170. <tr><td><button type="button" onclick="ample.$instance(this).acceptDialog();" class="xul-colorpicker-pane--button-accept">' + ample.locale.localize("xul.dialog.button.accept") + '</button></td></tr>\
  171. <tr><td height="3"></td></tr>\
  172. <tr><td><button type="button" onclick="ample.$instance(this).cancelDialog()" class="xul-colorpicker-pane--button-cancel">' + ample.locale.localize("xul.dialog.button.cancel") + '</button></td></tr>\
  173. </tbody>\
  174. </table>\
  175. </td>\
  176. </tr>\
  177. </tbody>\
  178. </table>\
  179. </div>';
  180. };
  181. cXULElement_colorpicker_pane.prototype.$getTagClose = function() {
  182. return '';
  183. };
  184. // Static methods
  185. cXULElement_colorpicker_pane._XYBtoRGB = function(oXYB) {
  186. var nH = 360 / 256 * oXYB.x;
  187. var nS = 1 - oXYB.y / 256;
  188. var nV = 1 - oXYB.b;
  189. var nR, nG, nB;
  190. if (nS == 0)
  191. nR = nG = nB = nV;
  192. else
  193. {
  194. var nI = Math.floor(nH / 60);
  195. var nF = nH / 60 - nI;
  196. var nP = nV *(1 - nS);
  197. var nQ = nV *(1 - nS * nF);
  198. var nT = nV *(1 - nS * (1 - nF));
  199. switch (nI)
  200. {
  201. case 0: nR = nV; nG = nT; nB = nP; break;
  202. case 1: nR = nQ; nG = nV; nB = nP; break;
  203. case 2: nR = nP; nG = nV; nB = nT; break;
  204. case 3: nR = nP; nG = nQ; nB = nV; break;
  205. case 4: nR = nT; nG = nP; nB = nV; break;
  206. default: nR = nV; nG = nP; nB = nQ;
  207. }
  208. }
  209. return '#' + this._toHex(nR * 256) + this._toHex(nG * 256) + this._toHex(nB * 256);
  210. };
  211. cXULElement_colorpicker_pane._RGBtoXYB = function(sColor) {
  212. if (!sColor.match(/^#[0-9a-f]{6}$/i))
  213. return;
  214. var nR = parseInt(sColor.substr(1, 2), 16);
  215. var nG = parseInt(sColor.substr(3, 2), 16);
  216. var nB = parseInt(sColor.substr(5, 2), 16);
  217. var nV = Math.max(nR, nG, nB);
  218. var nX = Math.min(nR, nG, nB);
  219. var nS = (nV-nX) / nV;
  220. var nH = 0;
  221. var nRed =(nV - nR) / (nV - nX);
  222. var nGreen =(nV - nG) / (nV - nX);
  223. var nBlue =(nV - nB) / (nV - nX);
  224. if (nR == nV)
  225. nH =(nG == nX) ? 5 + nBlue : 1 - nGreen;
  226. else
  227. if (nG == nV)
  228. nH =(nB == nX) ? 1 + nRed : 3 - nBlue;
  229. else
  230. nH =(nR == nX) ? 3 + nGreen : 5 - nRed;
  231. nH /= 6;
  232. return {'x' : (nH * 255), 'y' : (255 - nS * 255), 'b' : 1 - nV / 255};
  233. };
  234. cXULElement_colorpicker_pane._toHex = function(nValue) {
  235. var sHexCharacters = "0123456789ABCDEF";
  236. if (nValue < 0)
  237. return "00";
  238. if (nValue > 255)
  239. return "FF";
  240. else
  241. return sHexCharacters.charAt(Math.floor(nValue / 16)) + sHexCharacters.charAt(nValue % 16);
  242. };
  243. // Register Element
  244. ample.extend(cXULElement_colorpicker_pane);