Javascript cleanup.
[rgbconverter.git] / RGB Converter.wdgt / Widget.js
1 /*=====================================================================*\
2 || ###################################################################
3 || # RGB Converter
4 || # Copyright (c)2002-2010 Blue Static
5 || #
6 || # This program is free software; you can redistribute it and/or modify
7 || # it under the terms of the GNU General Public License as published by
8 || # the Free Software Foundation; version 2 of the License.
9 || #
10 || # This program is distributed in the hope that it will be useful, but
11 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 || # more details.
14 || #
15 || # You should have received a copy of the GNU General Public License along
16 || # with this program; if not, write to the Free Software Foundation, Inc.,
17 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 || ###################################################################
19 \*=====================================================================*/
20
21 var colors_ = {
22 red : 60,
23 green : 60,
24 blue : 60,
25 hex : '3C3C3C'
26 };
27
28 var backShowing_ = false;
29
30 // ###################################################################
31 // widget init
32 function Setup()
33 {
34 Draw();
35 createGenericButton(document.getElementById("backbutton"), "Done", hide_back, 0);
36 }
37
38 // ###################################################################
39 // watches the three RGB fields to make sure they don't go over the limites
40 function OnRGBChange(color)
41 {
42 var field = document.getElementById(color + "input");
43
44 // Handle RGB triads that are pased into a single box.
45 if (triad = field.value.match(/(rgb)?\(?([0-9]{1,3}),\s?([0-9]{1,3}),\s?([0-9]{1,3})\)?/)) {
46 document.getElementById("redinput").value = triad[2];
47 document.getElementById("greeninput").value = triad[3];
48 document.getElementById("blueinput").value = triad[4];
49
50 rgbwatcher("red");
51 rgbwatcher("green");
52 rgbwatcher("blue");
53 return;
54 }
55
56 // sanitize the number
57 var newval = field.value.replace(/[^0-9\-\.]*/g, "");
58 newval = Math.floor(newval);
59
60 // make sure we don't go over 255
61 if (newval > 255) {
62 newval = 255;
63 } else if (newval < 0) {
64 newval = 0;
65 }
66
67 // update the text field
68 field.value = newval;
69
70 // set fields[]
71 colors_[color] = newval;
72
73 // set hex
74 UpdateHex();
75
76 // redraw the swatch
77 Draw();
78 }
79
80 // ###################################################################
81 function Draw()
82 {
83 var canvas = document.getElementById('wheel');
84 var context = canvas.getContext('2d');
85 var radius = canvas.width / 2 - 3;
86 var center = [canvas.width / 2, canvas.height / 2];
87 context.strokeStyle = 'black';
88
89 context.clearRect(0, 0, canvas.width, canvas.height);
90
91 if (backShowing_) {
92 // Draw dark baground gradient.
93 context.beginPath();
94 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
95 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
96 gradient.addColorStop(0, 'rgb(200, 200, 200)');
97 gradient.addColorStop(1, 'rgb(30, 30, 30)');
98 context.fillStyle = gradient;
99 context.fill();
100 context.closePath();
101 return;
102 }
103
104 // Draw the individual components. Start with red.
105 context.beginPath();
106 context.moveTo(center[0], center[1]);
107 context.arc(canvas.width / 2,
108 canvas.height / 2,
109 radius,
110 Math.PI * 4/3,
111 Math.PI * 6/3,
112 false);
113 context.lineTo(center[0], center[1]);
114 context.fillStyle = _GetComponentColorString('red');
115 context.fill();
116 context.stroke();
117
118 // Green component.
119 context.beginPath();
120 context.moveTo(center[0], center[1]);
121 context.arc(canvas.width / 2,
122 canvas.height / 2,
123 radius,
124 Math.PI * 0,
125 Math.PI * 2/3,
126 false);
127 context.lineTo(center[0], center[1]);
128 context.fillStyle = _GetComponentColorString('green');
129 context.fill();
130 context.stroke();
131
132 // Blue component.
133 context.beginPath();
134 context.moveTo(center[0], center[1]);
135 context.arc(canvas.width / 2,
136 canvas.height / 2,
137 radius,
138 Math.PI * 2/3,
139 Math.PI * 4/3,
140 false);
141 context.lineTo(center[0], center[1]);
142 context.fillStyle = _GetComponentColorString('blue');
143 context.fill();
144 context.stroke();
145
146 // Draw the sheen gradient.
147 context.beginPath();
148 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
149 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
150 gradient.addColorStop(0, 'rgba(255,255,255,.5)');
151 gradient.addColorStop(1, 'rgba(0,0,0,0)');
152 context.fillStyle = gradient;
153 context.fill();
154 context.closePath();
155
156 // Draw the inner wheel. WebKit in 10.6.5 (and maybe earlier) has a bug in
157 // which you can't fill a path after stroking it, or vice versa.
158 var _arc = function(c) {
159 c.arc(center[0], center[1], canvas.width / 4.75, 0, Math.PI * 2, true);
160 }
161 context.save();
162 context.beginPath();
163 _arc(context)
164 context.strokeStyle = 'rgb(30,30,30)';
165 context.stroke();
166
167 context.beginPath();
168 _arc(context);
169 context.fillStyle = _GetRGBColorString();
170 context.fill();
171 context.closePath();
172 delete _arc;
173 }
174
175 // ###################################################################
176 // Returns the rgb(,,,) color string.
177
178 function _GetRGBColorString()
179 {
180 return 'rgb(' + colors_.red + ',' + colors_.green + ',' + colors_.blue + ')';
181 }
182
183 // ###################################################################
184 // Returns an individual color component's color string.
185
186 function _GetComponentColorString(color)
187 {
188 if (color == 'red') {
189 return 'rgb(' + colors_.red + ',0,0)';
190 } else if (color == 'green') {
191 return 'rgb(0,' + colors_.green + ',0)';
192 } else if (color == 'blue') {
193 return 'rgb(0,0,' + colors_.blue + ')';
194 }
195 alert('Invalid color ' + color);
196 }
197
198 // ###################################################################
199 // watches the hex field for updates
200 function OnHexChanged()
201 {
202 var field = document.getElementById("hexinput");
203
204 // sanitize the hex
205 var newval = field.value.replace(/[^0-9a-f]*/gi, "");
206
207 // get the length
208 var length = newval.length;
209
210 // Trim the value.
211 if (length > 6) {
212 newval = newval.substr(0, 6);
213 } else if (length == 3) {
214 newval = newval.substr(0, 1) + newval.substr(0, 1) +
215 newval.substr(1, 1) + newval.substr(1, 1) +
216 newval.substr(2, 1) + newval.substr(2, 1);
217 } else if (length < 6) {
218 for (var i = length; i <= 6; i++) {
219 newval = "" + newval + "0";
220 }
221 }
222
223 // update the field
224 field.value = newval;
225
226 // update fields[]
227 colors_.hex = newval;
228
229 // set RGB
230 UpdateRGB();
231
232 // redraw the swatch
233 Draw();
234 }
235
236 // ###################################################################
237 // update the hex value
238 function UpdateHex()
239 {
240 var hexstr = _Dec2Hex(colors_.red) + _Dec2Hex(colors_.green) + _Dec2Hex(colors_.blue);
241 colors_.hex = hexstr;
242 document.getElementById("hexinput").value = hexstr;
243 }
244
245 // ###################################################################
246 // update the RGB values
247 function UpdateRGB()
248 {
249 // regex match the bits
250 var bits = colors_.hex.match(/(..)(..)(..)/);
251
252 colors_.red = _Hex2dDc(bits[1]);
253 colors_.green = _Hex2dDc(bits[2]);
254 colors_.blue = _Hex2dDc(bits[3]);
255
256 // construct the hex values
257 document.getElementById("redinput").value = colors_.red;
258 document.getElementById("greeninput").value = colors_.green;
259 document.getElementById("blueinput").value = colors_.blue;
260 }
261
262 // ###################################################################
263 // convert a decimal to a hexidecimal
264 function _Dec2Hex(dec)
265 {
266 var hexstr = "0123456789ABCDEF";
267 var low = dec % 16;
268 var high = (dec - low) / 16;
269 hex = "" + hexstr.charAt(high) + hexstr.charAt(low);
270
271 return hex.toString();
272 }
273
274 // ###################################################################
275 // converts a hexidecimal to a decimal
276 function _Hex2dDc(hex)
277 {
278 return parseInt(hex, 16);
279 }
280
281 // ###################################################################
282 // ###################################################################
283 // ###################################################################
284
285 // flip data
286
287 function show_back()
288 {
289 backShowing_ = true;
290
291 var front = document.getElementById("front");
292 var back = document.getElementById("back");
293
294 if (window.widget)
295 {
296 widget.prepareForTransition("ToBack");
297 }
298
299 front.style.display = "none";
300 back.style.display = "block";
301
302 if (window.widget)
303 {
304 setTimeout("widget.performTransition();", 0);
305 }
306
307 document.getElementById("fliprollie").style.display = "none";
308
309 Draw();
310 }
311
312 function hide_back()
313 {
314 backShowing_ = false;
315
316 var front = document.getElementById("front");
317 var back = document.getElementById("back");
318
319 if (window.widget)
320 {
321 widget.prepareForTransition("ToFront");
322 }
323
324 back.style.display = "none";
325 front.style.display = "block";
326
327 if (window.widget)
328 {
329 setTimeout("widget.performTransition();", 0);
330 }
331
332 Draw();
333 }
334
335 var flipShown = false;
336
337 var animation = {
338 duration : 0,
339 starttime : 0,
340 to : 1.0,
341 now : 0.0,
342 from : 0.0,
343 firstElement : null,
344 timer : null
345 };
346
347 function mousemove(event)
348 {
349 if (backShowing_)
350 return;
351
352 if (!flipShown)
353 {
354 if (animation.timer != null)
355 {
356 clearInterval(animation.timer);
357 animation.timer = null;
358 }
359
360 var starttime = (new Date).getTime() - 13;
361
362 animation.duration = 500;
363 animation.starttime = starttime;
364 animation.firstElement = document.getElementById("flip");
365 animation.timer = setInterval("animate();", 13);
366 animation.from = animation.now;
367 animation.to = 1.0;
368 animate();
369 flipShown = true;
370 }
371 }
372
373 function mouseexit(event)
374 {
375 if (backShowing_)
376 return;
377
378 if (flipShown)
379 {
380 // fade in the flip widget
381 if (animation.timer != null)
382 {
383 clearInterval (animation.timer);
384 animation.timer = null;
385 }
386
387 var starttime = (new Date).getTime() - 13;
388
389 animation.duration = 500;
390 animation.starttime = starttime;
391 animation.firstElement = document.getElementById("flip");
392 animation.timer = setInterval("animate();", 13);
393 animation.from = animation.now;
394 animation.to = 0.0;
395 animate();
396 flipShown = false;
397 }
398 }
399
400
401 function animate()
402 {
403 var T;
404 var ease;
405 var time = (new Date).getTime();
406
407 T = limit_3(time - animation.starttime, 0, animation.duration);
408
409 if (T >= animation.duration)
410 {
411 clearInterval(animation.timer);
412 animation.timer = null;
413 animation.now = animation.to;
414 }
415 else
416 {
417 ease = 0.5 - (0.5 * Math.cos(Math.PI * T / animation.duration));
418 animation.now = compute_next_float(animation.from, animation.to, ease);
419 }
420
421 animation.firstElement.style.opacity = animation.now;
422 }
423
424 function limit_3 (a, b, c)
425 {
426 return a < b ? b : (a > c ? c : a);
427 }
428
429 function compute_next_float(from, to, ease)
430 {
431 return from + (to - from) * ease;
432 }
433
434 function enterflip(event)
435 {
436 document.getElementById("fliprollie").style.display = "block";
437 }
438
439 function exitflip(event)
440 {
441 document.getElementById("fliprollie").style.display = "none";
442 }