68 |
69 |
74 |
Not getting the results you need? Email nprapps@npr.org for help or to request a custom chart!
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
90 | Reset Form
91 |
92 |
93 |
94 |
119 |
146 |
191 |
192 |
193 |
194 |
Export
195 | Create Chart Image
196 |
197 |
198 |
199 |
200 |
201 |
202 |
Add to Seamus
203 |
204 |
205 | Open the Seamus story editor and add an image by selecting "image" in the assets drawer.
206 | Click "browse" and locate the image you downloaded.
207 | Select the custom crop and expand the crop box to fit the entire image, including the title.
208 | Make sure "enlargement" is set to none, set the primary crop to "custom" and click "perform crop."
209 |
210 |
211 |
212 | Click "next" and add a source and caption for your chart. Always credit your data source!
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
This only exists to force the fonts to load.
222 |
223 |
224 |
225 |
226 |
227 |
228 |
232 |
233 |
Your chart is ready to download. Click the download button below to save the image to your computer.
234 |
(Designer? Click here to download an SVG. )
235 |
236 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
--------------------------------------------------------------------------------
/www/js/lib/StackBlur.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | StackBlur - a fast almost Gaussian Blur For Canvas
4 |
5 | Version: 0.5
6 | Author: Mario Klingemann
7 | Contact: mario@quasimondo.com
8 | Website: http://www.quasimondo.com/StackBlurForCanvas
9 | Twitter: @quasimondo
10 |
11 | In case you find this class useful - especially in commercial projects -
12 | I am not totally unhappy for a small donation to my PayPal account
13 | mario@quasimondo.de
14 |
15 | Or support me on flattr:
16 | https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript
17 |
18 | Copyright (c) 2010 Mario Klingemann
19 |
20 | Permission is hereby granted, free of charge, to any person
21 | obtaining a copy of this software and associated documentation
22 | files (the "Software"), to deal in the Software without
23 | restriction, including without limitation the rights to use,
24 | copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the
26 | Software is furnished to do so, subject to the following
27 | conditions:
28 |
29 | The above copyright notice and this permission notice shall be
30 | included in all copies or substantial portions of the Software.
31 |
32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
36 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
38 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
39 | OTHER DEALINGS IN THE SOFTWARE.
40 | */
41 |
42 | var mul_table = [
43 | 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
44 | 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
45 | 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
46 | 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
47 | 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
48 | 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
49 | 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
50 | 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
51 | 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
52 | 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
53 | 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
54 | 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
55 | 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
56 | 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
57 | 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
58 | 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259];
59 |
60 |
61 | var shg_table = [
62 | 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
63 | 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
64 | 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
65 | 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
66 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
67 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
68 | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
69 | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
70 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
71 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
72 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
73 | 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
74 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
75 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
76 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
77 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ];
78 |
79 | function premultiplyAlpha(imageData)
80 | {
81 | var pixels = imageData.data;
82 | var size = imageData.width * imageData.height * 4;
83 |
84 | for (var i=0; i
> shg_sum;
247 | pixels[yi+1] = (g_sum * mul_sum) >> shg_sum;
248 | pixels[yi+2] = (b_sum * mul_sum) >> shg_sum;
249 | pixels[yi+3] = (a_sum * mul_sum) >> shg_sum;
250 |
251 | r_sum -= r_out_sum;
252 | g_sum -= g_out_sum;
253 | b_sum -= b_out_sum;
254 | a_sum -= a_out_sum;
255 |
256 | r_out_sum -= stackIn.r;
257 | g_out_sum -= stackIn.g;
258 | b_out_sum -= stackIn.b;
259 | a_out_sum -= stackIn.a;
260 |
261 | p = ( yw + ( ( p = x + radius + 1 ) < widthMinus1 ? p : widthMinus1 ) ) << 2;
262 |
263 | r_in_sum += ( stackIn.r = pixels[p]);
264 | g_in_sum += ( stackIn.g = pixels[p+1]);
265 | b_in_sum += ( stackIn.b = pixels[p+2]);
266 | a_in_sum += ( stackIn.a = pixels[p+3]);
267 |
268 | r_sum += r_in_sum;
269 | g_sum += g_in_sum;
270 | b_sum += b_in_sum;
271 | a_sum += a_in_sum;
272 |
273 | stackIn = stackIn.next;
274 |
275 | r_out_sum += ( pr = stackOut.r );
276 | g_out_sum += ( pg = stackOut.g );
277 | b_out_sum += ( pb = stackOut.b );
278 | a_out_sum += ( pa = stackOut.a );
279 |
280 | r_in_sum -= pr;
281 | g_in_sum -= pg;
282 | b_in_sum -= pb;
283 | a_in_sum -= pa;
284 |
285 | stackOut = stackOut.next;
286 |
287 | yi += 4;
288 | }
289 | yw += width;
290 | }
291 |
292 |
293 | for ( x = 0; x < width; x++ )
294 | {
295 | g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
296 |
297 | yi = x << 2;
298 | r_out_sum = radiusPlus1 * ( pr = pixels[yi]);
299 | g_out_sum = radiusPlus1 * ( pg = pixels[yi+1]);
300 | b_out_sum = radiusPlus1 * ( pb = pixels[yi+2]);
301 | a_out_sum = radiusPlus1 * ( pa = pixels[yi+3]);
302 |
303 | r_sum += sumFactor * pr;
304 | g_sum += sumFactor * pg;
305 | b_sum += sumFactor * pb;
306 | a_sum += sumFactor * pa;
307 |
308 | stack = stackStart;
309 |
310 | for( i = 0; i < radiusPlus1; i++ )
311 | {
312 | stack.r = pr;
313 | stack.g = pg;
314 | stack.b = pb;
315 | stack.a = pa;
316 | stack = stack.next;
317 | }
318 |
319 | yp = width;
320 |
321 | for( i = 1; i <= radius; i++ )
322 | {
323 | yi = ( yp + x ) << 2;
324 |
325 | r_sum += ( stack.r = ( pr = pixels[yi])) * ( rbs = radiusPlus1 - i );
326 | g_sum += ( stack.g = ( pg = pixels[yi+1])) * rbs;
327 | b_sum += ( stack.b = ( pb = pixels[yi+2])) * rbs;
328 | a_sum += ( stack.a = ( pa = pixels[yi+3])) * rbs;
329 |
330 | r_in_sum += pr;
331 | g_in_sum += pg;
332 | b_in_sum += pb;
333 | a_in_sum += pa;
334 |
335 | stack = stack.next;
336 |
337 | if( i < heightMinus1 )
338 | {
339 | yp += width;
340 | }
341 | }
342 |
343 | yi = x;
344 | stackIn = stackStart;
345 | stackOut = stackEnd;
346 | for ( y = 0; y < height; y++ )
347 | {
348 | p = yi << 2;
349 | pixels[p] = (r_sum * mul_sum) >> shg_sum;
350 | pixels[p+1] = (g_sum * mul_sum) >> shg_sum;
351 | pixels[p+2] = (b_sum * mul_sum) >> shg_sum;
352 | pixels[p+3] = (a_sum * mul_sum) >> shg_sum;
353 |
354 | r_sum -= r_out_sum;
355 | g_sum -= g_out_sum;
356 | b_sum -= b_out_sum;
357 | a_sum -= a_out_sum;
358 |
359 | r_out_sum -= stackIn.r;
360 | g_out_sum -= stackIn.g;
361 | b_out_sum -= stackIn.b;
362 | a_out_sum -= stackIn.a;
363 |
364 | p = ( x + (( ( p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1 ) * width )) << 2;
365 |
366 | r_sum += ( r_in_sum += ( stackIn.r = pixels[p]));
367 | g_sum += ( g_in_sum += ( stackIn.g = pixels[p+1]));
368 | b_sum += ( b_in_sum += ( stackIn.b = pixels[p+2]));
369 | a_sum += ( a_in_sum += ( stackIn.a = pixels[p+3]));
370 |
371 | stackIn = stackIn.next;
372 |
373 | r_out_sum += ( pr = stackOut.r );
374 | g_out_sum += ( pg = stackOut.g );
375 | b_out_sum += ( pb = stackOut.b );
376 | a_out_sum += ( pa = stackOut.a );
377 |
378 | r_in_sum -= pr;
379 | g_in_sum -= pg;
380 | b_in_sum -= pb;
381 | a_in_sum -= pa;
382 |
383 | stackOut = stackOut.next;
384 |
385 | yi += width;
386 | }
387 | }
388 |
389 | unpremultiplyAlpha(imageData);
390 |
391 | context.putImageData( imageData, top_x, top_y );
392 | }
393 |
394 |
395 | function stackBlurCanvasRGB( id, top_x, top_y, width, height, radius )
396 | {
397 | if ( isNaN(radius) || radius < 1 ) return;
398 | radius |= 0;
399 |
400 | var canvas = document.getElementById( id );
401 | var context = canvas.getContext("2d");
402 | var imageData;
403 |
404 | try {
405 | try {
406 | imageData = context.getImageData( top_x, top_y, width, height );
407 | } catch(e) {
408 |
409 | // NOTE: this part is supposedly only needed if you want to work with local files
410 | // so it might be okay to remove the whole try/catch block and just use
411 | // imageData = context.getImageData( top_x, top_y, width, height );
412 | try {
413 | netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
414 | imageData = context.getImageData( top_x, top_y, width, height );
415 | } catch(e) {
416 | alert("Cannot access local image");
417 | throw new Error("unable to access local image data: " + e);
418 | return;
419 | }
420 | }
421 | } catch(e) {
422 | alert("Cannot access image");
423 | throw new Error("unable to access image data: " + e);
424 | }
425 |
426 | var pixels = imageData.data;
427 |
428 | var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum,
429 | r_out_sum, g_out_sum, b_out_sum,
430 | r_in_sum, g_in_sum, b_in_sum,
431 | pr, pg, pb, rbs;
432 |
433 | var div = radius + radius + 1;
434 | var w4 = width << 2;
435 | var widthMinus1 = width - 1;
436 | var heightMinus1 = height - 1;
437 | var radiusPlus1 = radius + 1;
438 | var sumFactor = radiusPlus1 * ( radiusPlus1 + 1 ) / 2;
439 |
440 | var stackStart = new BlurStack();
441 | var stack = stackStart;
442 | for ( i = 1; i < div; i++ )
443 | {
444 | stack = stack.next = new BlurStack();
445 | if ( i == radiusPlus1 ) var stackEnd = stack;
446 | }
447 | stack.next = stackStart;
448 | var stackIn = null;
449 | var stackOut = null;
450 |
451 | yw = yi = 0;
452 |
453 | var mul_sum = mul_table[radius];
454 | var shg_sum = shg_table[radius];
455 |
456 | for ( y = 0; y < height; y++ )
457 | {
458 | r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0;
459 |
460 | r_out_sum = radiusPlus1 * ( pr = pixels[yi] );
461 | g_out_sum = radiusPlus1 * ( pg = pixels[yi+1] );
462 | b_out_sum = radiusPlus1 * ( pb = pixels[yi+2] );
463 |
464 | r_sum += sumFactor * pr;
465 | g_sum += sumFactor * pg;
466 | b_sum += sumFactor * pb;
467 |
468 | stack = stackStart;
469 |
470 | for( i = 0; i < radiusPlus1; i++ )
471 | {
472 | stack.r = pr;
473 | stack.g = pg;
474 | stack.b = pb;
475 | stack = stack.next;
476 | }
477 |
478 | for( i = 1; i < radiusPlus1; i++ )
479 | {
480 | p = yi + (( widthMinus1 < i ? widthMinus1 : i ) << 2 );
481 | r_sum += ( stack.r = ( pr = pixels[p])) * ( rbs = radiusPlus1 - i );
482 | g_sum += ( stack.g = ( pg = pixels[p+1])) * rbs;
483 | b_sum += ( stack.b = ( pb = pixels[p+2])) * rbs;
484 |
485 | r_in_sum += pr;
486 | g_in_sum += pg;
487 | b_in_sum += pb;
488 |
489 | stack = stack.next;
490 | }
491 |
492 |
493 | stackIn = stackStart;
494 | stackOut = stackEnd;
495 | for ( x = 0; x < width; x++ )
496 | {
497 | pixels[yi] = (r_sum * mul_sum) >> shg_sum;
498 | pixels[yi+1] = (g_sum * mul_sum) >> shg_sum;
499 | pixels[yi+2] = (b_sum * mul_sum) >> shg_sum;
500 |
501 | r_sum -= r_out_sum;
502 | g_sum -= g_out_sum;
503 | b_sum -= b_out_sum;
504 |
505 | r_out_sum -= stackIn.r;
506 | g_out_sum -= stackIn.g;
507 | b_out_sum -= stackIn.b;
508 |
509 | p = ( yw + ( ( p = x + radius + 1 ) < widthMinus1 ? p : widthMinus1 ) ) << 2;
510 |
511 | r_in_sum += ( stackIn.r = pixels[p]);
512 | g_in_sum += ( stackIn.g = pixels[p+1]);
513 | b_in_sum += ( stackIn.b = pixels[p+2]);
514 |
515 | r_sum += r_in_sum;
516 | g_sum += g_in_sum;
517 | b_sum += b_in_sum;
518 |
519 | stackIn = stackIn.next;
520 |
521 | r_out_sum += ( pr = stackOut.r );
522 | g_out_sum += ( pg = stackOut.g );
523 | b_out_sum += ( pb = stackOut.b );
524 |
525 | r_in_sum -= pr;
526 | g_in_sum -= pg;
527 | b_in_sum -= pb;
528 |
529 | stackOut = stackOut.next;
530 |
531 | yi += 4;
532 | }
533 | yw += width;
534 | }
535 |
536 |
537 | for ( x = 0; x < width; x++ )
538 | {
539 | g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0;
540 |
541 | yi = x << 2;
542 | r_out_sum = radiusPlus1 * ( pr = pixels[yi]);
543 | g_out_sum = radiusPlus1 * ( pg = pixels[yi+1]);
544 | b_out_sum = radiusPlus1 * ( pb = pixels[yi+2]);
545 |
546 | r_sum += sumFactor * pr;
547 | g_sum += sumFactor * pg;
548 | b_sum += sumFactor * pb;
549 |
550 | stack = stackStart;
551 |
552 | for( i = 0; i < radiusPlus1; i++ )
553 | {
554 | stack.r = pr;
555 | stack.g = pg;
556 | stack.b = pb;
557 | stack = stack.next;
558 | }
559 |
560 | yp = width;
561 |
562 | for( i = 1; i <= radius; i++ )
563 | {
564 | yi = ( yp + x ) << 2;
565 |
566 | r_sum += ( stack.r = ( pr = pixels[yi])) * ( rbs = radiusPlus1 - i );
567 | g_sum += ( stack.g = ( pg = pixels[yi+1])) * rbs;
568 | b_sum += ( stack.b = ( pb = pixels[yi+2])) * rbs;
569 |
570 | r_in_sum += pr;
571 | g_in_sum += pg;
572 | b_in_sum += pb;
573 |
574 | stack = stack.next;
575 |
576 | if( i < heightMinus1 )
577 | {
578 | yp += width;
579 | }
580 | }
581 |
582 | yi = x;
583 | stackIn = stackStart;
584 | stackOut = stackEnd;
585 | for ( y = 0; y < height; y++ )
586 | {
587 | p = yi << 2;
588 | pixels[p] = (r_sum * mul_sum) >> shg_sum;
589 | pixels[p+1] = (g_sum * mul_sum) >> shg_sum;
590 | pixels[p+2] = (b_sum * mul_sum) >> shg_sum;
591 |
592 | r_sum -= r_out_sum;
593 | g_sum -= g_out_sum;
594 | b_sum -= b_out_sum;
595 |
596 | r_out_sum -= stackIn.r;
597 | g_out_sum -= stackIn.g;
598 | b_out_sum -= stackIn.b;
599 |
600 | p = ( x + (( ( p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1 ) * width )) << 2;
601 |
602 | r_sum += ( r_in_sum += ( stackIn.r = pixels[p]));
603 | g_sum += ( g_in_sum += ( stackIn.g = pixels[p+1]));
604 | b_sum += ( b_in_sum += ( stackIn.b = pixels[p+2]));
605 |
606 | stackIn = stackIn.next;
607 |
608 | r_out_sum += ( pr = stackOut.r );
609 | g_out_sum += ( pg = stackOut.g );
610 | b_out_sum += ( pb = stackOut.b );
611 |
612 | r_in_sum -= pr;
613 | g_in_sum -= pg;
614 | b_in_sum -= pb;
615 |
616 | stackOut = stackOut.next;
617 |
618 | yi += width;
619 | }
620 | }
621 |
622 | context.putImageData( imageData, top_x, top_y );
623 |
624 | }
625 |
626 | function BlurStack()
627 | {
628 | this.r = 0;
629 | this.g = 0;
630 | this.b = 0;
631 | this.a = 0;
632 | this.next = null;
633 | }
634 |
--------------------------------------------------------------------------------
/www/js/lib/csvkit.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | this.CSVKit = {};
3 |
4 | /* Utils */
5 |
6 | var ctor = function() {};
7 | var inherits = function(child, parent){
8 | ctor.prototype = parent.prototype;
9 | child.prototype = new ctor();
10 | child.prototype.constructor = child;
11 | };
12 |
13 | /* CSVKit.Reader */
14 |
15 | CSVKit.Reader = function(options) {
16 | options = options || {};
17 |
18 | this.separator = options.separator || ',';
19 | this.quote_char = options.quote_char || '"';
20 | this.escape_char = options.escape_char || '"';
21 | this.column_names = options.column_names || [];
22 | this.columns_from_header = 'columns_from_header' in options ? options.columns_from_header : true;
23 | this.nested_quotes = 'nested_quotes' in options ? options.nested_quotes : false;
24 | this.rows = [];
25 |
26 | this.state = {
27 | rows: 0,
28 | open_record: [],
29 | open_field: '',
30 | last_char: '',
31 | in_quoted_field: false
32 | };
33 | };
34 |
35 | CSVKit.Reader.prototype.parse = function(data) {
36 | if (this.state.open_record.length === 0) {
37 | if (data.charCodeAt(0) === 0xFEFF) {
38 | data = data.slice(1);
39 | }
40 | }
41 |
42 | for (var i = 0; i < data.length; i++) {
43 | var c = data.charAt(i), next_char;
44 | switch (c) {
45 | // escape and separator may be the same char, typically '"'
46 | case this.escape_char:
47 | case this.quote_char:
48 | var is_escape = false;
49 |
50 | if (c === this.escape_char) {
51 | next_char = data.charAt(i + 1);
52 |
53 | if (this._is_escapable(next_char)) {
54 | this._add_character(next_char);
55 | i++;
56 | is_escape = true;
57 | }
58 | }
59 | if (!is_escape && (c === this.quote_char)) {
60 | if (this.state.open_field && !this.state.in_quoted_field) {
61 | this.state.in_quoted_field = true;
62 | break;
63 | }
64 |
65 | if (this.state.in_quoted_field) {
66 | // closing quote should be followed by separator unless the nested quotes option is set
67 | next_char = data.charAt(i + 1);
68 |
69 | if (next_char && next_char !== '\r' && next_char != '\n' && next_char !== this.separator && this.nested_quotes !== true) {
70 | throw new Error("separator expected after a closing quote; found " + next_char);
71 | } else {
72 | this.state.in_quoted_field = false;
73 | }
74 | } else if (this.state.open_field === '') {
75 | this.state.in_quoted_field = true;
76 | }
77 | }
78 |
79 | break;
80 | case this.separator:
81 | if (this.state.in_quoted_field) {
82 | this._add_character(c);
83 | } else {
84 | this._add_field();
85 | }
86 | break;
87 | case '\n':
88 | // handle CRLF sequence
89 | if (!this.state.in_quoted_field && (this.state.last_char === '\r')) {
90 | break;
91 | }
92 | case '\r':
93 | if (this.state.in_quoted_field) {
94 | this._add_character(c);
95 | } else {
96 | this._add_field();
97 | this._add_record();
98 | }
99 | break;
100 | default:
101 | this._add_character(c);
102 | }
103 |
104 | this.state.last_char = c;
105 | }
106 |
107 | if (this.state.in_quoted_field) {
108 | throw new Error("Input stream ended but closing quotes expected");
109 | } else {
110 | if (this.state.open_field) {
111 | this._add_field();
112 | }
113 |
114 | if (this.state.open_record.length > 0) {
115 | this._add_record();
116 | }
117 | }
118 | };
119 |
120 | CSVKit.Reader.prototype._is_escapable = function(c) {
121 | if ((c === this.escape_char) || (c === this.quote_char)) {
122 | return true;
123 | }
124 | return false;
125 | };
126 |
127 | CSVKit.Reader.prototype._add_character = function(c) {
128 | this.state.open_field += c;
129 | };
130 |
131 | CSVKit.Reader.prototype._add_field = function() {
132 | this.state.open_record.push(this.state.open_field);
133 | this.state.open_field = '';
134 | this.state.in_quoted_field = false;
135 | };
136 |
137 | CSVKit.Reader.prototype._add_record = function() {
138 | if (this.columns_from_header && this.state.rows === 0) {
139 | this.column_names = this.state.open_record;
140 | } else {
141 | this.rows.push(this._serialize_record(this.state.open_record));
142 | }
143 |
144 | this.state.rows++;
145 | this.state.open_record = [];
146 | this.state.open_field = '';
147 | this.state.in_quoted_field = false;
148 | };
149 |
150 | CSVKit.Reader.prototype._serialize_record = function(record) {
151 | return record;
152 | };
153 |
154 | /* CSVKit.ObjectReader */
155 |
156 | CSVKit.ObjectReader = function(options) {
157 | CSVKit.Reader.call(this, options);
158 | };
159 | inherits(CSVKit.ObjectReader, CSVKit.Reader);
160 |
161 | CSVKit.ObjectReader.prototype._serialize_record = function(record) {
162 | var obj = {};
163 |
164 | for (var i = 0; i < this.column_names.length; i++) {
165 | obj[this.column_names[i]] = record[i];
166 | }
167 |
168 | return obj;
169 | };
170 |
171 | /* CSVKit.Writer */
172 |
173 | CSVKit.Writer = function(options) {
174 | options = options || {};
175 |
176 | this.separator = options.separator || ',';
177 | this.quote_char = options.quote_char || '"';
178 | this.escape_char = options.escape_char || '"';
179 | this.quote_all = options.quote_all || false;
180 | this.newline = '\n';
181 |
182 | CSVKit.Writer.prototype.write = function(rows) {
183 | var formatted_rows = [];
184 |
185 | for (var i = 0; i < rows.length; i++) {
186 | formatted_rows.push(this._serialize_row(rows[i]));
187 | }
188 |
189 | return formatted_rows.join(this.newline);
190 | };
191 |
192 | CSVKit.Writer.prototype._serialize_row = function(row) {
193 | var formatted_cells = [];
194 |
195 | for (var i = 0; i < row.length; i++) {
196 | formatted_cells.push(this._serialize_cell(row[i]));
197 | }
198 |
199 | return formatted_cells.join(this.separator);
200 | };
201 |
202 | CSVKit.Writer.prototype._serialize_cell = function(cell) {
203 | if (cell.indexOf(this.quote_char) >= 0) {
204 | cell = cell.replace(new RegExp(this.quote_char, 'g'), this.escape_char + this.quote_char);
205 | }
206 |
207 | if (this.quote_all || cell.indexOf(this.separator) >= 0 || cell.indexOf(this.newline) >= 0) {
208 | return this.quote_char + cell + this.quote_char;
209 | }
210 |
211 | return cell;
212 | };
213 | }
214 |
215 | /* CSVKit.ObjectWriter */
216 |
217 | CSVKit.ObjectWriter = function(options) {
218 | CSVKit.Writer.call(this, options);
219 |
220 | if (!('column_names' in options)) {
221 | throw "The column_names option is required.";
222 | }
223 |
224 | this.column_names = options.column_names;
225 | };
226 | inherits(CSVKit.ObjectWriter, CSVKit.Writer);
227 |
228 | CSVKit.ObjectWriter.prototype.write = function(rows) {
229 | var header = {};
230 |
231 | for (var i = 0; i < this.column_names.length; i++) {
232 | header[this.column_names[i]] = this.column_names[i];
233 | }
234 |
235 | rows.splice(0, 0, header);
236 |
237 | return CSVKit.Writer.prototype.write.call(this, rows);
238 | }
239 |
240 | CSVKit.ObjectWriter.prototype._serialize_row = function(row) {
241 | var cells = [];
242 |
243 | for (var i = 0; i < this.column_names.length; i++) {
244 | cells.push(row[this.column_names[i]]);
245 | }
246 |
247 | return CSVKit.Writer.prototype._serialize_row.call(this, cells);
248 | };
249 |
250 | }).call(this);
251 |
--------------------------------------------------------------------------------
/www/js/lib/jquery.colorPicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Really Simple Color Picker in jQuery
3 | *
4 | * Licensed under the MIT (MIT-LICENSE.txt) licenses.
5 | *
6 | * Copyright (c) 2008-2012
7 | * Lakshan Perera (www.laktek.com) & Daniel Lacy (daniellacy.com)
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy
10 | * of this software and associated documentation files (the "Software"), to
11 | * deal in the Software without restriction, including without limitation the
12 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 | * sell copies of the Software, and to permit persons to whom the Software is
14 | * furnished to do so, subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in
17 | * all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 | * IN THE SOFTWARE.
26 | */
27 |
28 | (function ($) {
29 | /**
30 | * Create a couple private variables.
31 | **/
32 | var selectorOwner,
33 | activePalette,
34 | cItterate = 0,
35 | templates = {
36 | control : $('
'),
37 | palette : $('
'),
38 | swatch : $('
'),
39 | hexLabel: $('Hex '),
40 | hexField: $(' ')
41 | },
42 | transparent = "transparent",
43 | lastColor;
44 |
45 | /**
46 | * Create our colorPicker function
47 | **/
48 | $.fn.colorPicker = function (options) {
49 |
50 | return this.each(function () {
51 | // Setup time. Clone new elements from our templates, set some IDs, make shortcuts, jazzercise.
52 | var element = $(this),
53 | opts = $.extend({}, $.fn.colorPicker.defaults, options),
54 | defaultColor = $.fn.colorPicker.toHex(
55 | (element.val().length > 0) ? element.val() : opts.pickerDefault
56 | ),
57 | newControl = templates.control.clone(),
58 | newPalette = templates.palette.clone().attr('id', 'colorPicker_palette-' + cItterate),
59 | newHexLabel = templates.hexLabel.clone(),
60 | newHexField = templates.hexField.clone(),
61 | paletteId = newPalette[0].id,
62 | swatch, controlText;
63 |
64 |
65 | /**
66 | * Build a color palette.
67 | **/
68 | $.each(opts.colors, function (i) {
69 | swatch = templates.swatch.clone();
70 |
71 | if (opts.colors[i] === transparent) {
72 | swatch.addClass(transparent).text('X');
73 | $.fn.colorPicker.bindPalette(newHexField, swatch, transparent);
74 | } else {
75 | swatch.css("background-color", "#" + this);
76 | $.fn.colorPicker.bindPalette(newHexField, swatch);
77 | }
78 | swatch.appendTo(newPalette);
79 | });
80 |
81 |
82 | newHexLabel.attr('for', 'colorPicker_hex-' + cItterate);
83 |
84 | newHexField.attr({
85 | 'id' : 'colorPicker_hex-' + cItterate,
86 | 'value' : defaultColor
87 | });
88 |
89 | newHexField.bind("keydown", function (event) {
90 | if (event.keyCode === 13) {
91 | var hexColor = $.fn.colorPicker.toHex($(this).val());
92 | $.fn.colorPicker.changeColor(hexColor ? hexColor : element.val());
93 | }
94 | if (event.keyCode === 27) {
95 | $.fn.colorPicker.hidePalette();
96 | }
97 | });
98 |
99 | newHexField.bind("keyup", function (event) {
100 | var hexColor = $.fn.colorPicker.toHex($(event.target).val());
101 | $.fn.colorPicker.previewColor(hexColor ? hexColor : element.val());
102 | });
103 |
104 | $('
').append(newHexLabel).appendTo(newPalette);
105 |
106 | newPalette.find('.colorPicker_hexWrap').append(newHexField);
107 | if (opts.showHexField === false) {
108 | newHexField.hide();
109 | newHexLabel.hide();
110 | }
111 |
112 | $("body").append(newPalette);
113 |
114 | newPalette.hide();
115 |
116 |
117 | /**
118 | * Build replacement interface for original color input.
119 | **/
120 | newControl.css("background-color", defaultColor);
121 |
122 | newControl.bind("click", function () {
123 | if( element.is( ':not(:disabled)' ) ) {
124 | $.fn.colorPicker.togglePalette($('#' + paletteId), $(this));
125 | }
126 | });
127 |
128 | // Bind the palette toggling to the input label
129 | element.prev().bind("click", function () {
130 | if( element.is( ':not(:disabled)' ) ) {
131 | $.fn.colorPicker.togglePalette($('#' + paletteId), $(newControl));
132 | }
133 | });
134 |
135 | if( options && options.onColorChange ) {
136 | newControl.data('onColorChange', options.onColorChange);
137 | } else {
138 | newControl.data('onColorChange', function() {} );
139 | }
140 |
141 | if (controlText = element.data('text'))
142 | newControl.html(controlText)
143 |
144 | element.after(newControl);
145 |
146 | element.bind("change", function () {
147 | element.next(".colorPicker-picker").css(
148 | "background-color", $.fn.colorPicker.toHex($(this).val())
149 | );
150 | });
151 |
152 | element.val(defaultColor);
153 |
154 | // Hide the original input.
155 | if (element[0].tagName.toLowerCase() === 'input') {
156 | try {
157 | element.attr('type', 'hidden')
158 | } catch(err) { // oldIE doesn't allow changing of input.type
159 | element.css('visibility', 'hidden').css('position', 'absolute')
160 | }
161 | } else {
162 | element.hide();
163 | }
164 |
165 | cItterate++;
166 | });
167 | };
168 |
169 | /**
170 | * Extend colorPicker with... all our functionality.
171 | **/
172 | $.extend(true, $.fn.colorPicker, {
173 | /**
174 | * Return a Hex color, convert an RGB value and return Hex, or return false.
175 | *
176 | * Inspired by http://code.google.com/p/jquery-color-utils
177 | **/
178 | toHex : function (color) {
179 | // If we have a standard or shorthand Hex color, return that value.
180 | if (color.match(/[0-9A-F]{6}|[0-9A-F]{3}$/i)) {
181 | return (color.charAt(0) === "#") ? color : ("#" + color);
182 |
183 | // Alternatively, check for RGB color, then convert and return it as Hex.
184 | } else if (color.match(/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/)) {
185 | var c = ([parseInt(RegExp.$1, 10), parseInt(RegExp.$2, 10), parseInt(RegExp.$3, 10)]),
186 | pad = function (str) {
187 | if (str.length < 2) {
188 | for (var i = 0, len = 2 - str.length; i < len; i++) {
189 | str = '0' + str;
190 | }
191 | }
192 |
193 | return str;
194 | };
195 |
196 | if (c.length === 3) {
197 | var r = pad(c[0].toString(16)),
198 | g = pad(c[1].toString(16)),
199 | b = pad(c[2].toString(16));
200 |
201 | return '#' + r + g + b;
202 | }
203 |
204 | // Otherwise we wont do anything.
205 | } else {
206 | return false;
207 |
208 | }
209 | },
210 |
211 | /**
212 | * Check whether user clicked on the selector or owner.
213 | **/
214 | checkMouse : function (event, paletteId) {
215 | var selector = activePalette,
216 | selectorParent = $(event.target).parents("#" + selector.attr('id')).length;
217 |
218 | if (event.target === $(selector)[0] || event.target === selectorOwner[0] || event.target === selectorOwner.siblings('label')[0] || event.target === selectorOwner.siblings('label')[0].outerHTML || selectorParent > 0) {
219 | return;
220 | }
221 |
222 | $.fn.colorPicker.hidePalette();
223 | },
224 |
225 | /**
226 | * Hide the color palette modal.
227 | **/
228 | hidePalette : function () {
229 | $(document).unbind("mousedown", $.fn.colorPicker.checkMouse);
230 |
231 | $('.colorPicker-palette').hide();
232 | },
233 |
234 | /**
235 | * Show the color palette modal.
236 | **/
237 | showPalette : function (palette) {
238 | var hexColor = selectorOwner.prev("input").val();
239 |
240 | palette.css({
241 | top: selectorOwner.offset().top + (selectorOwner.outerHeight()),
242 | left: selectorOwner.offset().left
243 | });
244 |
245 | $("#color_value").val(hexColor);
246 |
247 | palette.show();
248 |
249 | $(document).bind("mousedown", $.fn.colorPicker.checkMouse);
250 | },
251 |
252 | /**
253 | * Toggle visibility of the colorPicker palette.
254 | **/
255 | togglePalette : function (palette, origin) {
256 | // selectorOwner is the clicked .colorPicker-picker.
257 | if (origin) {
258 | selectorOwner = origin;
259 | }
260 |
261 | activePalette = palette;
262 |
263 | if (activePalette.is(':visible')) {
264 | $.fn.colorPicker.hidePalette();
265 |
266 | } else {
267 | $.fn.colorPicker.showPalette(palette);
268 |
269 | }
270 | },
271 |
272 | /**
273 | * Update the input with a newly selected color.
274 | **/
275 | changeColor : function (value) {
276 | selectorOwner.css("background-color", value);
277 | selectorOwner.prev("input").val(value).change();
278 |
279 | $.fn.colorPicker.hidePalette();
280 |
281 | selectorOwner.data('onColorChange').call(selectorOwner, $(selectorOwner).prev("input").attr("id"), value);
282 | },
283 |
284 |
285 | /**
286 | * Preview the input with a newly selected color.
287 | **/
288 | previewColor : function (value) {
289 | selectorOwner.css("background-color", value);
290 | },
291 |
292 | /**
293 | * Bind events to the color palette swatches.
294 | */
295 | bindPalette : function (paletteInput, element, color) {
296 | color = color ? color : $.fn.colorPicker.toHex(element.css("background-color"));
297 |
298 | element.bind({
299 | click : function (ev) {
300 | lastColor = color;
301 |
302 | $.fn.colorPicker.changeColor(color);
303 | },
304 | mouseover : function (ev) {
305 | lastColor = paletteInput.val();
306 |
307 | $(this).css("border-color", "#598FEF");
308 |
309 | paletteInput.val(color);
310 |
311 | $.fn.colorPicker.previewColor(color);
312 | },
313 | mouseout : function (ev) {
314 | $(this).css("border-color", "#000");
315 |
316 | paletteInput.val(selectorOwner.css("background-color"));
317 |
318 | paletteInput.val(lastColor);
319 |
320 | $.fn.colorPicker.previewColor(lastColor);
321 | }
322 | });
323 | }
324 | });
325 |
326 | /**
327 | * Default colorPicker options.
328 | *
329 | * These are publibly available for global modification using a setting such as:
330 | *
331 | * $.fn.colorPicker.defaults.colors = ['151337', '111111']
332 | *
333 | * They can also be applied on a per-bound element basis like so:
334 | *
335 | * $('#element1').colorPicker({pickerDefault: 'efefef', transparency: true});
336 | * $('#element2').colorPicker({pickerDefault: '333333', colors: ['333333', '111111']});
337 | *
338 | **/
339 | $.fn.colorPicker.defaults = {
340 | // colorPicker default selected color.
341 | pickerDefault : "FFFFFF",
342 |
343 | // Default color set.
344 | colors : [
345 | '000000', '993300', '333300', '000080', '333399', '333333', '800000', 'FF6600',
346 | '808000', '008000', '008080', '0000FF', '666699', '808080', 'FF0000', 'FF9900',
347 | '99CC00', '339966', '33CCCC', '3366FF', '800080', '999999', 'FF00FF', 'FFCC00',
348 | 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0', 'FF99CC', 'FFCC99',
349 | 'FFFF99', 'CCFFFF', '99CCFF', 'FFFFFF'
350 | ],
351 |
352 | // If we want to simply add more colors to the default set, use addColors.
353 | addColors : [],
354 |
355 | // Show hex field
356 | showHexField: true
357 | };
358 |
359 | })(jQuery);
360 |
--------------------------------------------------------------------------------
/www/js/lib/rgbcolor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A class to parse color values
3 | * @author Stoyan Stefanov
4 | * @link http://www.phpied.com/rgb-color-parser-in-javascript/
5 | * @license Use it if you like it
6 | */
7 | function RGBColor(color_string)
8 | {
9 | this.ok = false;
10 |
11 | // strip any leading #
12 | if (color_string.charAt(0) == '#') { // remove # if any
13 | color_string = color_string.substr(1,6);
14 | }
15 |
16 | color_string = color_string.replace(/ /g,'');
17 | color_string = color_string.toLowerCase();
18 |
19 | // before getting into regexps, try simple matches
20 | // and overwrite the input
21 | var simple_colors = {
22 | aliceblue: 'f0f8ff',
23 | antiquewhite: 'faebd7',
24 | aqua: '00ffff',
25 | aquamarine: '7fffd4',
26 | azure: 'f0ffff',
27 | beige: 'f5f5dc',
28 | bisque: 'ffe4c4',
29 | black: '000000',
30 | blanchedalmond: 'ffebcd',
31 | blue: '0000ff',
32 | blueviolet: '8a2be2',
33 | brown: 'a52a2a',
34 | burlywood: 'deb887',
35 | cadetblue: '5f9ea0',
36 | chartreuse: '7fff00',
37 | chocolate: 'd2691e',
38 | coral: 'ff7f50',
39 | cornflowerblue: '6495ed',
40 | cornsilk: 'fff8dc',
41 | crimson: 'dc143c',
42 | cyan: '00ffff',
43 | darkblue: '00008b',
44 | darkcyan: '008b8b',
45 | darkgoldenrod: 'b8860b',
46 | darkgray: 'a9a9a9',
47 | darkgreen: '006400',
48 | darkkhaki: 'bdb76b',
49 | darkmagenta: '8b008b',
50 | darkolivegreen: '556b2f',
51 | darkorange: 'ff8c00',
52 | darkorchid: '9932cc',
53 | darkred: '8b0000',
54 | darksalmon: 'e9967a',
55 | darkseagreen: '8fbc8f',
56 | darkslateblue: '483d8b',
57 | darkslategray: '2f4f4f',
58 | darkturquoise: '00ced1',
59 | darkviolet: '9400d3',
60 | deeppink: 'ff1493',
61 | deepskyblue: '00bfff',
62 | dimgray: '696969',
63 | dodgerblue: '1e90ff',
64 | feldspar: 'd19275',
65 | firebrick: 'b22222',
66 | floralwhite: 'fffaf0',
67 | forestgreen: '228b22',
68 | fuchsia: 'ff00ff',
69 | gainsboro: 'dcdcdc',
70 | ghostwhite: 'f8f8ff',
71 | gold: 'ffd700',
72 | goldenrod: 'daa520',
73 | gray: '808080',
74 | green: '008000',
75 | greenyellow: 'adff2f',
76 | honeydew: 'f0fff0',
77 | hotpink: 'ff69b4',
78 | indianred : 'cd5c5c',
79 | indigo : '4b0082',
80 | ivory: 'fffff0',
81 | khaki: 'f0e68c',
82 | lavender: 'e6e6fa',
83 | lavenderblush: 'fff0f5',
84 | lawngreen: '7cfc00',
85 | lemonchiffon: 'fffacd',
86 | lightblue: 'add8e6',
87 | lightcoral: 'f08080',
88 | lightcyan: 'e0ffff',
89 | lightgoldenrodyellow: 'fafad2',
90 | lightgrey: 'd3d3d3',
91 | lightgreen: '90ee90',
92 | lightpink: 'ffb6c1',
93 | lightsalmon: 'ffa07a',
94 | lightseagreen: '20b2aa',
95 | lightskyblue: '87cefa',
96 | lightslateblue: '8470ff',
97 | lightslategray: '778899',
98 | lightsteelblue: 'b0c4de',
99 | lightyellow: 'ffffe0',
100 | lime: '00ff00',
101 | limegreen: '32cd32',
102 | linen: 'faf0e6',
103 | magenta: 'ff00ff',
104 | maroon: '800000',
105 | mediumaquamarine: '66cdaa',
106 | mediumblue: '0000cd',
107 | mediumorchid: 'ba55d3',
108 | mediumpurple: '9370d8',
109 | mediumseagreen: '3cb371',
110 | mediumslateblue: '7b68ee',
111 | mediumspringgreen: '00fa9a',
112 | mediumturquoise: '48d1cc',
113 | mediumvioletred: 'c71585',
114 | midnightblue: '191970',
115 | mintcream: 'f5fffa',
116 | mistyrose: 'ffe4e1',
117 | moccasin: 'ffe4b5',
118 | navajowhite: 'ffdead',
119 | navy: '000080',
120 | oldlace: 'fdf5e6',
121 | olive: '808000',
122 | olivedrab: '6b8e23',
123 | orange: 'ffa500',
124 | orangered: 'ff4500',
125 | orchid: 'da70d6',
126 | palegoldenrod: 'eee8aa',
127 | palegreen: '98fb98',
128 | paleturquoise: 'afeeee',
129 | palevioletred: 'd87093',
130 | papayawhip: 'ffefd5',
131 | peachpuff: 'ffdab9',
132 | peru: 'cd853f',
133 | pink: 'ffc0cb',
134 | plum: 'dda0dd',
135 | powderblue: 'b0e0e6',
136 | purple: '800080',
137 | red: 'ff0000',
138 | rosybrown: 'bc8f8f',
139 | royalblue: '4169e1',
140 | saddlebrown: '8b4513',
141 | salmon: 'fa8072',
142 | sandybrown: 'f4a460',
143 | seagreen: '2e8b57',
144 | seashell: 'fff5ee',
145 | sienna: 'a0522d',
146 | silver: 'c0c0c0',
147 | skyblue: '87ceeb',
148 | slateblue: '6a5acd',
149 | slategray: '708090',
150 | snow: 'fffafa',
151 | springgreen: '00ff7f',
152 | steelblue: '4682b4',
153 | tan: 'd2b48c',
154 | teal: '008080',
155 | thistle: 'd8bfd8',
156 | tomato: 'ff6347',
157 | turquoise: '40e0d0',
158 | violet: 'ee82ee',
159 | violetred: 'd02090',
160 | wheat: 'f5deb3',
161 | white: 'ffffff',
162 | whitesmoke: 'f5f5f5',
163 | yellow: 'ffff00',
164 | yellowgreen: '9acd32'
165 | };
166 | for (var key in simple_colors) {
167 | if (color_string == key) {
168 | color_string = simple_colors[key];
169 | }
170 | }
171 | // emd of simple type-in colors
172 |
173 | // array of color definition objects
174 | var color_defs = [
175 | {
176 | re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
177 | example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
178 | process: function (bits){
179 | return [
180 | parseInt(bits[1]),
181 | parseInt(bits[2]),
182 | parseInt(bits[3])
183 | ];
184 | }
185 | },
186 | {
187 | re: /^(\w{2})(\w{2})(\w{2})$/,
188 | example: ['#00ff00', '336699'],
189 | process: function (bits){
190 | return [
191 | parseInt(bits[1], 16),
192 | parseInt(bits[2], 16),
193 | parseInt(bits[3], 16)
194 | ];
195 | }
196 | },
197 | {
198 | re: /^(\w{1})(\w{1})(\w{1})$/,
199 | example: ['#fb0', 'f0f'],
200 | process: function (bits){
201 | return [
202 | parseInt(bits[1] + bits[1], 16),
203 | parseInt(bits[2] + bits[2], 16),
204 | parseInt(bits[3] + bits[3], 16)
205 | ];
206 | }
207 | }
208 | ];
209 |
210 | // search through the definitions to find a match
211 | for (var i = 0; i < color_defs.length; i++) {
212 | var re = color_defs[i].re;
213 | var processor = color_defs[i].process;
214 | var bits = re.exec(color_string);
215 | if (bits) {
216 | channels = processor(bits);
217 | this.r = channels[0];
218 | this.g = channels[1];
219 | this.b = channels[2];
220 | this.ok = true;
221 | }
222 |
223 | }
224 |
225 | // validate/cleanup values
226 | this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
227 | this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
228 | this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
229 |
230 | // some getters
231 | this.toRGB = function () {
232 | return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
233 | }
234 | this.toHex = function () {
235 | var r = this.r.toString(16);
236 | var g = this.g.toString(16);
237 | var b = this.b.toString(16);
238 | if (r.length == 1) r = '0' + r;
239 | if (g.length == 1) g = '0' + g;
240 | if (b.length == 1) b = '0' + b;
241 | return '#' + r + g + b;
242 | }
243 |
244 | // help
245 | this.getHelpXML = function () {
246 |
247 | var examples = new Array();
248 | // add regexps
249 | for (var i = 0; i < color_defs.length; i++) {
250 | var example = color_defs[i].example;
251 | for (var j = 0; j < example.length; j++) {
252 | examples[examples.length] = example[j];
253 | }
254 | }
255 | // add type-in colors
256 | for (var sc in simple_colors) {
257 | examples[examples.length] = sc;
258 | }
259 |
260 | var xml = document.createElement('ul');
261 | xml.setAttribute('id', 'rgbcolor-examples');
262 | for (var i = 0; i < examples.length; i++) {
263 | try {
264 | var list_item = document.createElement('li');
265 | var list_color = new RGBColor(examples[i]);
266 | var example_div = document.createElement('div');
267 | example_div.style.cssText =
268 | 'margin: 3px; '
269 | + 'border: 1px solid black; '
270 | + 'background:' + list_color.toHex() + '; '
271 | + 'color:' + list_color.toHex()
272 | ;
273 | example_div.appendChild(document.createTextNode('test'));
274 | var list_item_value = document.createTextNode(
275 | ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
276 | );
277 | list_item.appendChild(example_div);
278 | list_item.appendChild(list_item_value);
279 | xml.appendChild(list_item);
280 |
281 | } catch(e){}
282 | }
283 | return xml;
284 |
285 | }
286 |
287 | }
288 |
--------------------------------------------------------------------------------