~ubuntu-branches/ubuntu/jaunty/moodle/jaunty

« back to all changes in this revision

Viewing changes to lib/yui/colorpicker/colorpicker-debug.js

  • Committer: Bazaar Package Importer
  • Author(s): Jordan Mantha, Matt Oquist
  • Date: 2009-02-25 15:16:22 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090225151622-0ekt1liwhv2obfza
Tags: 1.9.4.dfsg-0ubuntu1
* Merge with Debian git (Closes LP: #322961, #239481, #334611):
  - use Ubuntu's smarty lib directory for linking
  - use internal yui library 
  - add update-notifier support back in

[Matt Oquist]
  * renamed prerm script
  * significantly rewrote postinst and other maintainer scripts to improve
    user experience and package maintainability
    (Closes LP: #225662, #325450, #327843, #303078, #234609)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 2.6.0
 
6
*/
 
7
/**
 
8
 * Provides color conversion and validation utils
 
9
 * @class YAHOO.util.Color
 
10
 * @namespace YAHOO.util
 
11
 */
 
12
YAHOO.util.Color = function() {
 
13
 
 
14
    var HCHARS="0123456789ABCDEF", lang=YAHOO.lang;
 
15
 
 
16
    return {
 
17
 
 
18
        /**
 
19
         * Converts 0-1 to 0-255
 
20
         * @method real2dec
 
21
         * @param n {float} the number to convert
 
22
         * @return {int} a number 0-255
 
23
         */
 
24
        real2dec: function(n) {
 
25
            return Math.min(255, Math.round(n*256));
 
26
        },
 
27
 
 
28
        /**
 
29
         * Converts HSV (h[0-360], s[0-1]), v[0-1] to RGB [255,255,255]
 
30
         * @method hsv2rgb
 
31
         * @param h {int|[int, float, float]} the hue, or an
 
32
         *        array containing all three parameters
 
33
         * @param s {float} the saturation
 
34
         * @param v {float} the value/brightness
 
35
         * @return {[int, int, int]} the red, green, blue values in
 
36
         *          decimal.
 
37
         */
 
38
        hsv2rgb: function(h, s, v) { 
 
39
 
 
40
            if (lang.isArray(h)) {
 
41
                return this.hsv2rgb.call(this, h[0], h[1], h[2]);
 
42
            }
 
43
 
 
44
            var r, g, b, i, f, p, q, t;
 
45
            i = Math.floor((h/60)%6);
 
46
            f = (h/60)-i;
 
47
            p = v*(1-s);
 
48
            q = v*(1-f*s);
 
49
            t = v*(1-(1-f)*s);
 
50
            switch(i) {
 
51
                case 0: r=v; g=t; b=p; break;
 
52
                case 1: r=q; g=v; b=p; break;
 
53
                case 2: r=p; g=v; b=t; break;
 
54
                case 3: r=p; g=q; b=v; break;
 
55
                case 4: r=t; g=p; b=v; break;
 
56
                case 5: r=v; g=p; b=q; break;
 
57
            }
 
58
 
 
59
            var fn=this.real2dec;
 
60
 
 
61
            return [fn(r), fn(g), fn(b)];
 
62
        },
 
63
 
 
64
        /**
 
65
         * Converts to RGB [255,255,255] to HSV (h[0-360], s[0-1]), v[0-1]
 
66
         * @method rgb2hsv
 
67
         * @param r {int|[int, int, int]} the red value, or an
 
68
         *        array containing all three parameters
 
69
         * @param g {int} the green value
 
70
         * @param b {int} the blue value
 
71
         * @return {[int, float, float]} the value converted to hsv
 
72
         */
 
73
        rgb2hsv: function(r, g, b) {
 
74
 
 
75
            if (lang.isArray(r)) {
 
76
                return this.rgb2hsv.call(this, r[0], r[1], r[2]);
 
77
            }
 
78
 
 
79
            r=r/255;
 
80
            g=g/255;
 
81
            b=b/255;
 
82
 
 
83
            var min,max,delta,h,s,v;
 
84
            min = Math.min(Math.min(r,g),b);
 
85
            max = Math.max(Math.max(r,g),b);
 
86
            delta = max-min;
 
87
 
 
88
            switch (max) {
 
89
                case min: h=0; break;
 
90
                case r:   h=60*(g-b)/delta; 
 
91
                          if (g<b) {
 
92
                              h+=360;
 
93
                          }
 
94
                          break;
 
95
                case g:   h=(60*(b-r)/delta)+120; break;
 
96
                case b:   h=(60*(r-g)/delta)+240; break;
 
97
            }
 
98
            
 
99
            s = (max === 0) ? 0 : 1-(min/max);
 
100
 
 
101
            var hsv = [Math.round(h), s, max];
 
102
 
 
103
            return hsv;
 
104
 
 
105
        },
 
106
 
 
107
        /**
 
108
         * Converts decimal rgb values into a hex string
 
109
         * 255,255,255 -> FFFFFF
 
110
         * @method rgb2hex
 
111
         * @param r {int|[int, int, int]} the red value, or an
 
112
         *        array containing all three parameters
 
113
         * @param g {int} the green value
 
114
         * @param b {int} the blue value
 
115
         * @return {string} the hex string
 
116
         */
 
117
        rgb2hex: function(r, g, b) {
 
118
            if (lang.isArray(r)) {
 
119
                return this.rgb2hex.call(this, r[0], r[1], r[2]);
 
120
            }
 
121
 
 
122
            var f=this.dec2hex;
 
123
            return f(r) + f(g) + f(b);
 
124
        },
 
125
     
 
126
        /**
 
127
         * Converts an int 0...255 to hex pair 00...FF
 
128
         * @method dec2hex
 
129
         * @param n {int} the number to convert
 
130
         * @return {string} the hex equivalent
 
131
         */
 
132
        dec2hex: function(n) {
 
133
            n = parseInt(n, 10);
 
134
            n = (lang.isNumber(n)) ? n : 0;
 
135
            n = (n > 255 || n < 0) ? 0 : n;
 
136
 
 
137
            return HCHARS.charAt((n - n % 16) / 16) + HCHARS.charAt(n % 16);
 
138
        },
 
139
 
 
140
        /**
 
141
         * Converts a hex pair 00...FF to an int 0...255 
 
142
         * @method hex2dec
 
143
         * @param str {string} the hex pair to convert
 
144
         * @return {int} the decimal
 
145
         */
 
146
        hex2dec: function(str) {
 
147
            var f = function(c) {
 
148
                return HCHARS.indexOf(c.toUpperCase());
 
149
            };
 
150
 
 
151
            var s=str.split('');
 
152
            
 
153
            return ((f(s[0]) * 16) + f(s[1]));
 
154
        },
 
155
 
 
156
        /**
 
157
         * Converts a hex string to rgb
 
158
         * @method hex2rgb
 
159
         * @param str {string} the hex string
 
160
         * @return {[int, int, int]} an array containing the rgb values
 
161
         */
 
162
        hex2rgb: function(s) { 
 
163
            var f = this.hex2dec;
 
164
            return [f(s.substr(0, 2)), f(s.substr(2, 2)), f(s.substr(4, 2))];
 
165
        },
 
166
 
 
167
        /**
 
168
         * Returns the closest websafe color to the supplied rgb value.
 
169
         * @method websafe
 
170
         * @param r {int|[int, int, int]} the red value, or an
 
171
         *        array containing all three parameters
 
172
         * @param g {int} the green value
 
173
         * @param b {int} the blue value
 
174
         * @return {[int, int, int]} an array containing the closes
 
175
         *                           websafe rgb colors.
 
176
         */
 
177
        websafe: function(r, g, b) {
 
178
 
 
179
            if (lang.isArray(r)) {
 
180
                return this.websafe.call(this, r[0], r[1], r[2]);
 
181
            }
 
182
 
 
183
            // returns the closest match [0, 51, 102, 153, 204, 255]
 
184
            var f = function(v) {
 
185
                if (lang.isNumber(v)) {
 
186
                    v = Math.min(Math.max(0, v), 255);
 
187
                    var i, next;
 
188
                    for (i=0; i<256; i=i+51) {
 
189
                        next = i+51;
 
190
                        if (v >= i && v <= next) {
 
191
                            return (v-i > 25) ? next : i;
 
192
                        }
 
193
                    }
 
194
 YAHOO.log("Error calculating the websafe value for " + v, "warn");
 
195
                }
 
196
 
 
197
                return v;
 
198
            };
 
199
 
 
200
            return [f(r), f(g), f(b)];
 
201
        }
 
202
    };
 
203
}();
 
204
 
 
205
 
 
206
(function() {
 
207
 
 
208
    var _pickercount = 0;
 
209
 
 
210
    /**
 
211
     * The colorpicker module provides a widget for selecting colors
 
212
     * @module colorpicker
 
213
     * @requires yahoo, dom, event, element, slider
 
214
     */
 
215
 
 
216
 
 
217
    /**
 
218
     * Creates the host element if it doesn't exist
 
219
     * @method _createHostElement
 
220
     * @private
 
221
     */
 
222
    var _createHostElement = function() {
 
223
        var el = document.createElement('div');
 
224
 
 
225
        if (this.CSS.BASE) {
 
226
            el.className = this.CSS.BASE;
 
227
        }
 
228
        
 
229
        return el;
 
230
    };
 
231
 
 
232
    /**
 
233
     * A widget to select colors
 
234
     * @namespace YAHOO.widget
 
235
     * @class YAHOO.widget.ColorPicker
 
236
     * @extends YAHOO.util.Element
 
237
     * @constructor
 
238
     * @param {HTMLElement | String | Object} el(optional) The html 
 
239
     * element that represents the colorpicker, or the attribute object to use. 
 
240
     * An element will be created if none provided.
 
241
     * @param {Object} attr (optional) A key map of the colorpicker's 
 
242
     * initial attributes.  Ignored if first arg is attributes object.
 
243
     */
 
244
    YAHOO.widget.ColorPicker = function(el, attr) {
 
245
        _pickercount = _pickercount + 1;
 
246
        this.logger = new YAHOO.widget.LogWriter("ColorPicker");
 
247
        attr = attr || {};
 
248
        if (arguments.length === 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
 
249
            attr = el; // treat first arg as attr object
 
250
            el = attr.element || null;
 
251
        }
 
252
        
 
253
        if (!el && !attr.element) { // create if we dont have one
 
254
            this.logger.log("creating host element");
 
255
            el = _createHostElement.call(this, attr);
 
256
        }
 
257
 
 
258
        YAHOO.widget.ColorPicker.superclass.constructor.call(this, el, attr); 
 
259
    };
 
260
 
 
261
    YAHOO.extend(YAHOO.widget.ColorPicker, YAHOO.util.Element);
 
262
    
 
263
    var proto = YAHOO.widget.ColorPicker.prototype,
 
264
        Slider=YAHOO.widget.Slider,
 
265
        Color=YAHOO.util.Color,
 
266
        Dom = YAHOO.util.Dom,
 
267
        Event = YAHOO.util.Event,
 
268
        lang = YAHOO.lang,
 
269
        sub = lang.substitute;
 
270
    
 
271
 
 
272
    var b = "yui-picker";
 
273
 
 
274
    /**
 
275
     * The element ids used by this control
 
276
     * @property ID
 
277
     * @final
 
278
     */
 
279
    proto.ID = {
 
280
 
 
281
        /**
 
282
         * The id for the "red" form field
 
283
         * @property ID.R
 
284
         * @type String
 
285
         * @final
 
286
         * @default yui-picker-r
 
287
         */
 
288
        R: b + "-r",
 
289
 
 
290
        /**
 
291
         * The id for the "red" hex pair output
 
292
         * @property ID.R_HEX
 
293
         * @type String
 
294
         * @final
 
295
         * @default yui-picker-rhex
 
296
         */
 
297
        R_HEX: b + "-rhex",
 
298
 
 
299
        /**
 
300
         * The id for the "green" form field
 
301
         * @property ID.G
 
302
         * @type String
 
303
         * @final
 
304
         * @default yui-picker-g
 
305
         */
 
306
        G: b + "-g",
 
307
 
 
308
        /**
 
309
         * The id for the "green" hex pair output
 
310
         * @property ID.G_HEX
 
311
         * @type String
 
312
         * @final
 
313
         * @default yui-picker-ghex
 
314
         */
 
315
        G_HEX: b + "-ghex",
 
316
 
 
317
 
 
318
        /**
 
319
         * The id for the "blue" form field
 
320
         * @property ID.B
 
321
         * @type String
 
322
         * @final
 
323
         * @default yui-picker-b
 
324
         */
 
325
        B: b + "-b",
 
326
 
 
327
        /**
 
328
         * The id for the "blue" hex pair output
 
329
         * @property ID.B_HEX
 
330
         * @type String
 
331
         * @final
 
332
         * @default yui-picker-bhex
 
333
         */
 
334
        B_HEX: b + "-bhex",
 
335
 
 
336
        /**
 
337
         * The id for the "hue" form field
 
338
         * @property ID.H
 
339
         * @type String
 
340
         * @final
 
341
         * @default yui-picker-h
 
342
         */
 
343
        H: b + "-h",
 
344
 
 
345
        /**
 
346
         * The id for the "saturation" form field
 
347
         * @property ID.S
 
348
         * @type String
 
349
         * @final
 
350
         * @default yui-picker-s
 
351
         */
 
352
        S: b + "-s",
 
353
 
 
354
        /**
 
355
         * The id for the "value" form field
 
356
         * @property ID.V
 
357
         * @type String
 
358
         * @final
 
359
         * @default yui-picker-v
 
360
         */
 
361
        V: b + "-v",
 
362
 
 
363
        /**
 
364
         * The id for the picker region slider
 
365
         * @property ID.PICKER_BG
 
366
         * @type String
 
367
         * @final
 
368
         * @default yui-picker-bg
 
369
         */
 
370
        PICKER_BG:      b + "-bg",
 
371
 
 
372
        /**
 
373
         * The id for the picker region thumb
 
374
         * @property ID.PICKER_THUMB
 
375
         * @type String
 
376
         * @final
 
377
         * @default yui-picker-thumb
 
378
         */
 
379
        PICKER_THUMB:   b + "-thumb",
 
380
 
 
381
        /**
 
382
         * The id for the hue slider
 
383
         * @property ID.HUE_BG
 
384
         * @type String
 
385
         * @final
 
386
         * @default yui-picker-hue-bg
 
387
         */
 
388
        HUE_BG:         b + "-hue-bg",
 
389
 
 
390
        /**
 
391
         * The id for the hue thumb
 
392
         * @property ID.HUE_THUMB
 
393
         * @type String
 
394
         * @final
 
395
         * @default yui-picker-hue-thumb
 
396
         */
 
397
        HUE_THUMB:      b + "-hue-thumb",
 
398
 
 
399
        /**
 
400
         * The id for the hex value form field
 
401
         * @property ID.HEX
 
402
         * @type String
 
403
         * @final
 
404
         * @default yui-picker-hex
 
405
         */
 
406
        HEX:            b + "-hex",
 
407
 
 
408
        /**
 
409
         * The id for the color swatch
 
410
         * @property ID.SWATCH
 
411
         * @type String
 
412
         * @final
 
413
         * @default yui-picker-swatch
 
414
         */
 
415
        SWATCH:         b + "-swatch",
 
416
 
 
417
        /**
 
418
         * The id for the websafe color swatch
 
419
         * @property ID.WEBSAFE_SWATCH
 
420
         * @type String
 
421
         * @final
 
422
         * @default yui-picker-websafe-swatch
 
423
         */
 
424
        WEBSAFE_SWATCH: b + "-websafe-swatch",
 
425
 
 
426
        /**
 
427
         * The id for the control details
 
428
         * @property ID.CONTROLS
 
429
         * @final
 
430
         * @default yui-picker-controls
 
431
         */
 
432
        CONTROLS: b + "-controls",
 
433
 
 
434
        /**
 
435
         * The id for the rgb controls
 
436
         * @property ID.RGB_CONTROLS
 
437
         * @final
 
438
         * @default yui-picker-rgb-controls
 
439
         */
 
440
        RGB_CONTROLS: b + "-rgb-controls",
 
441
 
 
442
        /**
 
443
         * The id for the hsv controls
 
444
         * @property ID.HSV_CONTROLS
 
445
         * @final
 
446
         * @default yui-picker-hsv-controls
 
447
         */
 
448
        HSV_CONTROLS: b + "-hsv-controls",
 
449
        
 
450
        /**
 
451
         * The id for the hsv controls
 
452
         * @property ID.HEX_CONTROLS
 
453
         * @final
 
454
         * @default yui-picker-hex-controls
 
455
         */
 
456
        HEX_CONTROLS: b + "-hex-controls",
 
457
 
 
458
        /**
 
459
         * The id for the hex summary
 
460
         * @property ID.HEX_SUMMARY
 
461
         * @final
 
462
         * @default yui-picker-hex-summary
 
463
         */
 
464
        HEX_SUMMARY: b + "-hex-summary",
 
465
 
 
466
        /**
 
467
         * The id for the controls section header
 
468
         * @property ID.CONTROLS_LABEL
 
469
         * @final
 
470
         * @default yui-picker-controls-label
 
471
         */
 
472
        CONTROLS_LABEL: b + "-controls-label"
 
473
    };
 
474
 
 
475
    /**
 
476
     * Constants for any script-generated messages.  The values here
 
477
     * are the default messages.  They can be updated by providing
 
478
     * the complete list to the constructor for the "txt" attribute.
 
479
     * @property TXT
 
480
     * @final
 
481
     */
 
482
    proto.TXT = {
 
483
        ILLEGAL_HEX: "Illegal hex value entered",
 
484
        SHOW_CONTROLS: "Show color details",
 
485
        HIDE_CONTROLS: "Hide color details",
 
486
        CURRENT_COLOR: "Currently selected color: {rgb}",
 
487
        CLOSEST_WEBSAFE: "Closest websafe color: {rgb}. Click to select.",
 
488
        R: "R",
 
489
        G: "G",
 
490
        B: "B",
 
491
        H: "H",
 
492
        S: "S",
 
493
        V: "V",
 
494
        HEX: "#",
 
495
        DEG: "\u00B0",
 
496
        PERCENT: "%"
 
497
    };
 
498
 
 
499
    /**
 
500
     * Constants for the default image locations for img tags that are
 
501
     * generated by the control.  They can be modified by passing the
 
502
     * complete list to the contructor for the "images" attribute
 
503
     * @property IMAGE
 
504
     * @final
 
505
     */
 
506
    proto.IMAGE = {
 
507
        PICKER_THUMB: "../../build/colorpicker/assets/picker_thumb.png",
 
508
        HUE_THUMB: "../../build/colorpicker/assets/hue_thumb.png"
 
509
    };
 
510
 
 
511
    /*
 
512
     * Constants for the control's custom event names.  subscribe
 
513
     * to the rgbChange event instead.
 
514
     * @property EVENT
 
515
     * @final
 
516
     */
 
517
    //proto.EVENT = {
 
518
        //CHANGE: "change"
 
519
    //};
 
520
 
 
521
    //proto.CSS = { };
 
522
 
 
523
    /**
 
524
     * Constants for the control's default default values
 
525
     * @property DEFAULT
 
526
     * @final
 
527
     */
 
528
    proto.DEFAULT = {
 
529
        PICKER_SIZE: 180
 
530
    };
 
531
 
 
532
    /**
 
533
     * Constants for the control's configuration attributes
 
534
     * @property OPT
 
535
     * @final
 
536
     */
 
537
    proto.OPT = {
 
538
        HUE: "hue",
 
539
        SATURATION: "saturation",
 
540
        VALUE: "value",
 
541
        RED: "red",
 
542
        GREEN: "green",
 
543
        BLUE: "blue",
 
544
        HSV: "hsv",
 
545
        RGB: "rgb",
 
546
        WEBSAFE: "websafe",
 
547
        HEX: "hex",
 
548
        PICKER_SIZE: "pickersize",
 
549
        SHOW_CONTROLS: "showcontrols",
 
550
        SHOW_RGB_CONTROLS: "showrgbcontrols",
 
551
        SHOW_HSV_CONTROLS: "showhsvcontrols",
 
552
        SHOW_HEX_CONTROLS: "showhexcontrols",
 
553
        SHOW_HEX_SUMMARY: "showhexsummary",
 
554
        SHOW_WEBSAFE: "showwebsafe",
 
555
        //SHOW_SUBMIT: "showsubmit",
 
556
        CONTAINER: "container",
 
557
        IDS: "ids",
 
558
        ELEMENTS: "elements",
 
559
        TXT: "txt",
 
560
        IMAGES: "images",
 
561
        ANIMATE: "animate"
 
562
    };
 
563
 
 
564
    /**
 
565
     * Moves the hue slider into the position dictated by the current state
 
566
     * of the control
 
567
     * @method _updateHueSlider
 
568
     * @private
 
569
     */
 
570
    var _updateHueSlider = function() {
 
571
        var size = this.get(this.OPT.PICKER_SIZE),
 
572
            h = this.get(this.OPT.HUE);
 
573
 
 
574
        h = size - Math.round(h / 360 * size);
 
575
        
 
576
        // 0 is at the top and bottom of the hue slider.  Always go to
 
577
        // the top so we don't end up sending the thumb to the bottom
 
578
        // when the value didn't actually change (e.g., a conversion
 
579
        // produced 360 instead of 0 and the value was already 0).
 
580
        if (h === size) {
 
581
            h = 0;
 
582
        }
 
583
        this.logger.log("Hue slider is being set to " + h);
 
584
 
 
585
        this.hueSlider.setValue(h);
 
586
    };
 
587
 
 
588
    /**
 
589
     * Moves the picker slider into the position dictated by the current state
 
590
     * of the control
 
591
     * @method _updatePickerSlider
 
592
     * @private
 
593
     */
 
594
    var _updatePickerSlider = function() {
 
595
        var size = this.get(this.OPT.PICKER_SIZE),
 
596
            s = this.get(this.OPT.SATURATION),
 
597
            v = this.get(this.OPT.VALUE);
 
598
 
 
599
        s = Math.round(s * size / 100);
 
600
        v = Math.round(size - (v * size / 100));
 
601
 
 
602
        this.logger.log("Setting picker slider to " + [s, v]);
 
603
 
 
604
        this.pickerSlider.setRegionValue(s, v);
 
605
    };
 
606
 
 
607
    /**
 
608
     * Moves the sliders into the position dictated by the current state
 
609
     * of the control
 
610
     * @method _updateSliders
 
611
     * @private
 
612
     */
 
613
    var _updateSliders = function() {
 
614
        _updateHueSlider.call(this);
 
615
        _updatePickerSlider.call(this);
 
616
    };
 
617
 
 
618
    /**
 
619
     * Sets the control to the specified rgb value and
 
620
     * moves the sliders to the proper positions
 
621
     * @method setValue
 
622
     * @param rgb {[int, int, int]} the rgb value
 
623
     * @param silent {boolean} whether or not to fire the change event
 
624
     */
 
625
    proto.setValue = function(rgb, silent) {
 
626
        silent = (silent) || false;
 
627
        this.set(this.OPT.RGB, rgb, silent);
 
628
        _updateSliders.call(this);
 
629
    };
 
630
 
 
631
    /**
 
632
     * The hue slider
 
633
     * @property hueSlider
 
634
     * @type YAHOO.widget.Slider
 
635
     */
 
636
    proto.hueSlider = null; 
 
637
    
 
638
    /**
 
639
     * The picker region
 
640
     * @property pickerSlider
 
641
     * @type YAHOO.widget.Slider
 
642
     */
 
643
    proto.pickerSlider = null;
 
644
 
 
645
    /**
 
646
     * Translates the slider value into hue, int[0,359]
 
647
     * @method _getH
 
648
     * @private
 
649
     * @return {int} the hue from 0 to 359
 
650
     */
 
651
    var _getH = function() {
 
652
        var size = this.get(this.OPT.PICKER_SIZE),
 
653
            h = (size - this.hueSlider.getValue()) / size;
 
654
        h = Math.round(h*360);
 
655
        return (h === 360) ? 0 : h;
 
656
    };
 
657
 
 
658
    /**
 
659
     * Translates the slider value into saturation, int[0,1], left to right
 
660
     * @method _getS
 
661
     * @private
 
662
     * @return {int} the saturation from 0 to 1
 
663
     */
 
664
    var _getS = function() {
 
665
        return this.pickerSlider.getXValue() / this.get(this.OPT.PICKER_SIZE);
 
666
    };
 
667
 
 
668
    /**
 
669
     * Translates the slider value into value/brightness, int[0,1], top
 
670
     * to bottom
 
671
     * @method _getV
 
672
     * @private
 
673
     * @return {int} the value from 0 to 1
 
674
     */
 
675
    var _getV = function() {
 
676
        var size = this.get(this.OPT.PICKER_SIZE);
 
677
        return (size - this.pickerSlider.getYValue()) / size;
 
678
    };
 
679
 
 
680
    /**
 
681
     * Updates the background of the swatch with the current rbg value.
 
682
     * Also updates the websafe swatch to the closest websafe color
 
683
     * @method _updateSwatch
 
684
     * @private
 
685
     */
 
686
    var _updateSwatch = function() {
 
687
        var rgb = this.get(this.OPT.RGB),
 
688
            websafe = this.get(this.OPT.WEBSAFE),
 
689
            el = this.getElement(this.ID.SWATCH),
 
690
            color = rgb.join(","),
 
691
            txt = this.get(this.OPT.TXT);
 
692
 
 
693
        Dom.setStyle(el, "background-color", "rgb(" + color  + ")");
 
694
        el.title = lang.substitute(txt.CURRENT_COLOR, {
 
695
                "rgb": "#" + this.get(this.OPT.HEX)
 
696
            });
 
697
 
 
698
 
 
699
        el = this.getElement(this.ID.WEBSAFE_SWATCH);
 
700
        color = websafe.join(",");
 
701
 
 
702
        Dom.setStyle(el, "background-color", "rgb(" + color + ")");
 
703
        el.title = lang.substitute(txt.CLOSEST_WEBSAFE, {
 
704
                "rgb": "#" + Color.rgb2hex(websafe)
 
705
            });
 
706
 
 
707
    };
 
708
 
 
709
    /**
 
710
     * Reads the sliders and converts the values to RGB, updating the
 
711
     * internal state for all the individual form fields
 
712
     * @method _getValuesFromSliders
 
713
     * @private
 
714
     */
 
715
    var _getValuesFromSliders = function() {
 
716
        var h=_getH.call(this), s=_getS.call(this), v=_getV.call(this);
 
717
        YAHOO.log("hsv " + [h, s, v]);
 
718
 
 
719
        var rgb = Color.hsv2rgb(h, s, v);
 
720
        //var websafe = Color.websafe(rgb);
 
721
        //var hex = Color.rgb2hex(rgb[0], rgb[1], rgb[2]);
 
722
 
 
723
        this.set(this.OPT.RGB, rgb);
 
724
    };
 
725
 
 
726
    /**
 
727
     * Updates the form field controls with the state data contained
 
728
     * in the control.
 
729
     * @method _updateFormFields
 
730
     * @private
 
731
     */
 
732
    var _updateFormFields = function() {
 
733
        this.getElement(this.ID.H).value = this.get(this.OPT.HUE);
 
734
        this.getElement(this.ID.S).value = this.get(this.OPT.SATURATION);
 
735
        this.getElement(this.ID.V).value = this.get(this.OPT.VALUE);
 
736
        this.getElement(this.ID.R).value = this.get(this.OPT.RED);
 
737
        this.getElement(this.ID.R_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.RED));
 
738
        this.getElement(this.ID.G).value = this.get(this.OPT.GREEN);
 
739
        this.getElement(this.ID.G_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.GREEN));
 
740
        this.getElement(this.ID.B).value = this.get(this.OPT.BLUE);
 
741
        this.getElement(this.ID.B_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.BLUE));
 
742
        this.getElement(this.ID.HEX).value = this.get(this.OPT.HEX);
 
743
    };
 
744
 
 
745
    /**
 
746
     * Event handler for the hue slider.
 
747
     * @method _onHueSliderChange
 
748
     * @param newOffset {int} pixels from the start position
 
749
     * @private
 
750
     */
 
751
    var _onHueSliderChange = function(newOffset) {
 
752
        this.logger.log("hue update: " + newOffset , "warn");
 
753
 
 
754
        var h = _getH.call(this);
 
755
        this.set(this.OPT.HUE, h, true);
 
756
 
 
757
        // set picker background to the hue
 
758
        var rgb = Color.hsv2rgb(h, 1, 1);
 
759
        var styleDef = "rgb(" + rgb.join(",") + ")";
 
760
 
 
761
        Dom.setStyle(this.getElement(this.ID.PICKER_BG), "background-color", styleDef);
 
762
 
 
763
        if (this.hueSlider.valueChangeSource === this.hueSlider.SOURCE_UI_EVENT) {
 
764
            _getValuesFromSliders.call(this);
 
765
        }
 
766
 
 
767
        _updateFormFields.call(this);
 
768
        _updateSwatch.call(this);
 
769
    };
 
770
 
 
771
    /**
 
772
     * Event handler for the picker slider, which controls the
 
773
     * saturation and value/brightness.
 
774
     * @method _onPickerSliderChange
 
775
     * @param newOffset {{x: int, y: int}} x/y pixels from the start position
 
776
     * @private
 
777
     */
 
778
    var _onPickerSliderChange = function(newOffset) {
 
779
        this.logger.log(sub("picker update [{x}, {y}]", newOffset));
 
780
 
 
781
        var s=_getS.call(this), v=_getV.call(this);
 
782
        this.set(this.OPT.SATURATION, Math.round(s*100), true);
 
783
        this.set(this.OPT.VALUE, Math.round(v*100), true);
 
784
 
 
785
        if (this.pickerSlider.valueChangeSource === this.pickerSlider.SOURCE_UI_EVENT) {
 
786
            _getValuesFromSliders.call(this);
 
787
        }
 
788
 
 
789
        _updateFormFields.call(this);
 
790
        _updateSwatch.call(this);
 
791
    };
 
792
 
 
793
 
 
794
    /**
 
795
     * Key map to well-known commands for txt field input
 
796
     * @method _getCommand
 
797
     * @param e {Event} the keypress or keydown event
 
798
     * @return {int} a command code
 
799
     * <ul>
 
800
     * <li>0 = not a number, letter in range, or special key</li>
 
801
     * <li>1 = number</li>
 
802
     * <li>2 = a-fA-F</li>
 
803
     * <li>3 = increment (up arrow)</li>
 
804
     * <li>4 = decrement (down arrow)</li>
 
805
     * <li>5 = special key (tab, delete, return, escape, left, right)</li> 
 
806
     * <li>6 = return</li>
 
807
     * </ul>
 
808
     * @private
 
809
     */
 
810
    var _getCommand = function(e) {
 
811
        var c = Event.getCharCode(e);
 
812
 
 
813
        //alert(Event.getCharCode(e) + ", " + e.keyCode + ", " + e.charCode);
 
814
 
 
815
        // special keys
 
816
        if (c === 38) { // up arrow
 
817
            return 3;
 
818
        } else if (c === 13) { // return
 
819
            return 6;
 
820
        } else if (c === 40) { // down array
 
821
            return 4;
 
822
        } else if (c >= 48 && c<=57) { // 0-9
 
823
            return 1;
 
824
        } else if (c >= 97 && c<=102) { // a-f
 
825
            return 2;
 
826
        } else if (c >= 65 && c<=70) { // A-F
 
827
            return 2;
 
828
        //} else if ("8, 9, 13, 27, 37, 39".indexOf(c) > -1 || 
 
829
        //              (c >= 112 && c <=123)) { // including F-keys
 
830
        // tab, delete, return, escape, left, right
 
831
        } else if ("8, 9, 13, 27, 37, 39".indexOf(c) > -1) { // special chars
 
832
            return 5;
 
833
        } else { // something we probably don't want
 
834
            return 0;
 
835
        }
 
836
    };
 
837
 
 
838
    /**
 
839
     * Use the value of the text field to update the control
 
840
     * @method _hexFieldKeypress
 
841
     * @param e {Event} an event
 
842
     * @param el {HTMLElement} the field
 
843
     * @param prop {string} the key to the linked property
 
844
     * @private
 
845
     */
 
846
    var _useFieldValue = function(e, el, prop) {
 
847
        var val = el.value;
 
848
 
 
849
        if (prop !== this.OPT.HEX) {
 
850
            val = parseInt(val, 10);
 
851
        }
 
852
 
 
853
        if (val !== this.get(prop)) {
 
854
            this.set(prop, val);
 
855
        }
 
856
    };
 
857
 
 
858
    /**
 
859
     * Handle keypress on one of the rgb or hsv fields.
 
860
     * @method _rgbFieldKeypress
 
861
     * @param e {Event} the keypress event
 
862
     * @param el {HTMLElement} the field
 
863
     * @param prop {string} the key to the linked property
 
864
     * @private
 
865
     */
 
866
    var _rgbFieldKeypress = function(e, el, prop) {
 
867
        var command = _getCommand(e);
 
868
        var inc = (e.shiftKey) ? 10 : 1;
 
869
        switch (command) {
 
870
            case 6: // return, update the value
 
871
                _useFieldValue.apply(this, arguments);
 
872
                break;
 
873
                        
 
874
            case 3: // up arrow, increment
 
875
                this.set(prop, Math.min(this.get(prop)+inc, 255));
 
876
                _updateFormFields.call(this);
 
877
                //Event.stopEvent(e);
 
878
                break;
 
879
            case 4: // down arrow, decrement
 
880
                this.set(prop, Math.max(this.get(prop)-inc, 0));
 
881
                _updateFormFields.call(this);
 
882
                //Event.stopEvent(e);
 
883
                break;
 
884
 
 
885
            default:
 
886
        }
 
887
 
 
888
    };
 
889
 
 
890
    /**
 
891
     * Handle keydown on the hex field
 
892
     * @method _hexFieldKeypress
 
893
     * @param e {Event} the keypress event
 
894
     * @param el {HTMLElement} the field
 
895
     * @param prop {string} the key to the linked property
 
896
     * @private
 
897
     */
 
898
    var _hexFieldKeypress = function(e, el, prop) {
 
899
        var command = _getCommand(e);
 
900
        if (command === 6) { // return, update the value
 
901
            _useFieldValue.apply(this, arguments);
 
902
        }
 
903
    };
 
904
 
 
905
    /** 
 
906
     * Allows numbers and special chars, and by default allows a-f.  
 
907
     * Used for the hex field keypress handler.
 
908
     * @method _hexOnly
 
909
     * @param e {Event} the event
 
910
     * @param numbersOnly omits a-f if set to true
 
911
     * @private
 
912
     * @return {boolean} false if we are canceling the event
 
913
     */
 
914
    var _hexOnly = function(e, numbersOnly) {
 
915
        var command = _getCommand(e);
 
916
        switch (command) {
 
917
            case 6: // return
 
918
            case 5: // special char
 
919
            case 1: // number
 
920
                break;
 
921
            case 2: // hex char (a-f)
 
922
                if (numbersOnly !== true) {
 
923
                    break;
 
924
                }
 
925
 
 
926
                // fallthrough is intentional
 
927
 
 
928
            default: // prevent alpha and punctuation
 
929
                Event.stopEvent(e);
 
930
                return false;
 
931
        }
 
932
    };
 
933
 
 
934
    /** 
 
935
     * Allows numbers and special chars only.  Used for the
 
936
     * rgb and hsv fields keypress handler.
 
937
     * @method _numbersOnly
 
938
     * @param e {Event} the event
 
939
     * @private
 
940
     * @return {boolean} false if we are canceling the event
 
941
     */
 
942
    var _numbersOnly = function(e) {
 
943
        return _hexOnly(e, true);
 
944
    };
 
945
 
 
946
    /**
 
947
     * Returns the element reference that is saved.  The id can be either
 
948
     * the element id, or the key for this id in the "id" config attribute.
 
949
     * For instance, the host element id can be obtained by passing its
 
950
     * id (default: "yui_picker") or by its key "YUI_PICKER".
 
951
     * @param id {string} the element id, or key 
 
952
     * @return {HTMLElement} a reference to the element
 
953
     */
 
954
    proto.getElement = function(id) { 
 
955
        return this.get(this.OPT.ELEMENTS)[this.get(this.OPT.IDS)[id]]; 
 
956
    };
 
957
 
 
958
    var _createElements = function() {
 
959
        this.logger.log("Building markup");
 
960
        var el, child, img, fld, i, 
 
961
            ids = this.get(this.OPT.IDS),
 
962
            txt = this.get(this.OPT.TXT),
 
963
            images = this.get(this.OPT.IMAGES),
 
964
            Elem = function(type, o) {
 
965
                var n = document.createElement(type);
 
966
                if (o) {
 
967
                    lang.augmentObject(n, o, true);
 
968
                }
 
969
                return n;
 
970
            },
 
971
            RGBElem = function(type, obj) {
 
972
                var o = lang.merge({
 
973
                        //type: "txt",
 
974
                        autocomplete: "off",
 
975
                        value: "0",
 
976
                        size: 3,
 
977
                        maxlength: 3
 
978
                    }, obj);
 
979
 
 
980
                o.name = o.id;
 
981
                return new Elem(type, o);
 
982
            };
 
983
 
 
984
        var p = this.get("element");
 
985
 
 
986
        // Picker slider (S and V) ---------------------------------------------
 
987
 
 
988
        el = new Elem("div", {
 
989
            id: ids[this.ID.PICKER_BG],
 
990
            className: "yui-picker-bg",
 
991
            tabIndex: -1,
 
992
            hideFocus: true
 
993
        });
 
994
 
 
995
        child = new Elem("div", {
 
996
            id: ids[this.ID.PICKER_THUMB],
 
997
            className: "yui-picker-thumb"
 
998
        });
 
999
 
 
1000
        img = new Elem("img", {
 
1001
            src: images.PICKER_THUMB
 
1002
        });
 
1003
 
 
1004
        child.appendChild(img);
 
1005
        el.appendChild(child);
 
1006
        p.appendChild(el);
 
1007
        
 
1008
        // Hue slider ---------------------------------------------
 
1009
        el = new Elem("div", {
 
1010
            id: ids[this.ID.HUE_BG],
 
1011
            className: "yui-picker-hue-bg",
 
1012
            tabIndex: -1,
 
1013
            hideFocus: true
 
1014
        });
 
1015
 
 
1016
        child = new Elem("div", {
 
1017
            id: ids[this.ID.HUE_THUMB],
 
1018
            className: "yui-picker-hue-thumb"
 
1019
        });
 
1020
 
 
1021
        img = new Elem("img", {
 
1022
            src: images.HUE_THUMB
 
1023
        });
 
1024
 
 
1025
        child.appendChild(img);
 
1026
        el.appendChild(child);
 
1027
        p.appendChild(el);
 
1028
 
 
1029
 
 
1030
        // controls ---------------------------------------------
 
1031
 
 
1032
        el = new Elem("div", {
 
1033
            id: ids[this.ID.CONTROLS],
 
1034
            className: "yui-picker-controls"
 
1035
        });
 
1036
 
 
1037
        p.appendChild(el);
 
1038
        p = el;
 
1039
 
 
1040
            // controls header
 
1041
            el = new Elem("div", {
 
1042
                className: "hd"
 
1043
            });
 
1044
 
 
1045
            child = new Elem("a", {
 
1046
                id: ids[this.ID.CONTROLS_LABEL],
 
1047
                //className: "yui-picker-controls-label",
 
1048
                href: "#"
 
1049
            });
 
1050
            el.appendChild(child);
 
1051
            p.appendChild(el);
 
1052
 
 
1053
            // bd
 
1054
            el = new Elem("div", {
 
1055
                className: "bd"
 
1056
            });
 
1057
 
 
1058
            p.appendChild(el);
 
1059
            p = el;
 
1060
 
 
1061
                // rgb
 
1062
                el = new Elem("ul", {
 
1063
                    id: ids[this.ID.RGB_CONTROLS],
 
1064
                    className: "yui-picker-rgb-controls"
 
1065
                });
 
1066
 
 
1067
                child = new Elem("li");
 
1068
                child.appendChild(document.createTextNode(txt.R + " "));
 
1069
 
 
1070
                fld = new RGBElem("input", {
 
1071
                    id: ids[this.ID.R],
 
1072
                    className: "yui-picker-r"
 
1073
                });
 
1074
 
 
1075
                child.appendChild(fld);
 
1076
                el.appendChild(child);
 
1077
 
 
1078
                child = new Elem("li");
 
1079
                child.appendChild(document.createTextNode(txt.G + " "));
 
1080
 
 
1081
                fld = new RGBElem("input", {
 
1082
                    id: ids[this.ID.G],
 
1083
                    className: "yui-picker-g"
 
1084
                });
 
1085
 
 
1086
                child.appendChild(fld);
 
1087
                el.appendChild(child);
 
1088
 
 
1089
                child = new Elem("li");
 
1090
                child.appendChild(document.createTextNode(txt.B + " "));
 
1091
 
 
1092
                fld = new RGBElem("input", {
 
1093
                    id: ids[this.ID.B],
 
1094
                    className: "yui-picker-b"
 
1095
                });
 
1096
 
 
1097
                child.appendChild(fld);
 
1098
                el.appendChild(child);
 
1099
 
 
1100
                p.appendChild(el);
 
1101
 
 
1102
                // hsv
 
1103
                el = new Elem("ul", {
 
1104
                    id: ids[this.ID.HSV_CONTROLS],
 
1105
                    className: "yui-picker-hsv-controls"
 
1106
                });
 
1107
 
 
1108
                child = new Elem("li");
 
1109
                child.appendChild(document.createTextNode(txt.H + " "));
 
1110
 
 
1111
                fld = new RGBElem("input", {
 
1112
                    id: ids[this.ID.H],
 
1113
                    className: "yui-picker-h"
 
1114
                });
 
1115
 
 
1116
                child.appendChild(fld);
 
1117
                child.appendChild(document.createTextNode(" " + txt.DEG));
 
1118
 
 
1119
                el.appendChild(child);
 
1120
 
 
1121
                child = new Elem("li");
 
1122
                child.appendChild(document.createTextNode(txt.S + " "));
 
1123
 
 
1124
                fld = new RGBElem("input", {
 
1125
                    id: ids[this.ID.S],
 
1126
                    className: "yui-picker-s"
 
1127
                });
 
1128
 
 
1129
                child.appendChild(fld);
 
1130
                child.appendChild(document.createTextNode(" " + txt.PERCENT));
 
1131
 
 
1132
                el.appendChild(child);
 
1133
 
 
1134
                child = new Elem("li");
 
1135
                child.appendChild(document.createTextNode(txt.V + " "));
 
1136
 
 
1137
                fld = new RGBElem("input", {
 
1138
                    id: ids[this.ID.V],
 
1139
                    className: "yui-picker-v"
 
1140
                });
 
1141
 
 
1142
                child.appendChild(fld);
 
1143
                child.appendChild(document.createTextNode(" " + txt.PERCENT));
 
1144
 
 
1145
                el.appendChild(child);
 
1146
                p.appendChild(el);
 
1147
 
 
1148
 
 
1149
                // hex summary
 
1150
 
 
1151
                el = new Elem("ul", {
 
1152
                    id: ids[this.ID.HEX_SUMMARY],
 
1153
                    className: "yui-picker-hex_summary"
 
1154
                });
 
1155
 
 
1156
                child = new Elem("li", {
 
1157
                    id: ids[this.ID.R_HEX]
 
1158
                });
 
1159
                el.appendChild(child);
 
1160
 
 
1161
                child = new Elem("li", {
 
1162
                    id: ids[this.ID.G_HEX]
 
1163
                });
 
1164
                el.appendChild(child);
 
1165
 
 
1166
                child = new Elem("li", {
 
1167
                    id: ids[this.ID.B_HEX]
 
1168
                });
 
1169
                el.appendChild(child);
 
1170
                p.appendChild(el);
 
1171
 
 
1172
                // hex field
 
1173
                el = new Elem("div", {
 
1174
                    id: ids[this.ID.HEX_CONTROLS],
 
1175
                    className: "yui-picker-hex-controls"
 
1176
                });
 
1177
                el.appendChild(document.createTextNode(txt.HEX + " "));
 
1178
 
 
1179
                child = new RGBElem("input", {
 
1180
                    id: ids[this.ID.HEX],
 
1181
                    className: "yui-picker-hex",
 
1182
                    size: 6,
 
1183
                    maxlength: 6
 
1184
                });
 
1185
 
 
1186
                el.appendChild(child);
 
1187
                p.appendChild(el);
 
1188
 
 
1189
                p = this.get("element");
 
1190
 
 
1191
                // swatch
 
1192
                el = new Elem("div", {
 
1193
                    id: ids[this.ID.SWATCH],
 
1194
                    className: "yui-picker-swatch"
 
1195
                });
 
1196
 
 
1197
                p.appendChild(el);
 
1198
 
 
1199
                // websafe swatch
 
1200
                el = new Elem("div", {
 
1201
                    id: ids[this.ID.WEBSAFE_SWATCH],
 
1202
                    className: "yui-picker-websafe-swatch"
 
1203
                });
 
1204
 
 
1205
                p.appendChild(el);
 
1206
 
 
1207
    };
 
1208
 
 
1209
    var _attachRGBHSV = function(id, config) {
 
1210
        Event.on(this.getElement(id), "keydown", function(e, me) {
 
1211
                _rgbFieldKeypress.call(me, e, this, config);
 
1212
            }, this);
 
1213
        Event.on(this.getElement(id), "keypress", _numbersOnly, this);
 
1214
        Event.on(this.getElement(id), "blur", function(e, me) {
 
1215
                _useFieldValue.call(me, e, this, config);
 
1216
            }, this);
 
1217
    };
 
1218
 
 
1219
 
 
1220
    /**
 
1221
     * Updates the rgb attribute with the current state of the r,g,b
 
1222
     * fields.  This is invoked from change listeners on these
 
1223
     * attributes to facilitate updating these values from the
 
1224
     * individual form fields
 
1225
     * @method _updateRGB
 
1226
     * @private
 
1227
     */
 
1228
    var _updateRGB = function() {
 
1229
        var rgb = [this.get(this.OPT.RED), 
 
1230
                   this.get(this.OPT.GREEN),
 
1231
                   this.get(this.OPT.BLUE)];
 
1232
 
 
1233
        this.logger.log("RGB value set to " + rgb);
 
1234
        this.set(this.OPT.RGB, rgb);
 
1235
 
 
1236
        _updateSliders.call(this);
 
1237
    };
 
1238
 
 
1239
    /**
 
1240
     * Sets the initial state of the sliders
 
1241
     * @method initPicker
 
1242
     */
 
1243
    proto.initPicker = function () {
 
1244
 
 
1245
        // bind all of our elements
 
1246
        var o=this.OPT, 
 
1247
            ids = this.get(o.IDS), 
 
1248
            els = this.get(o.ELEMENTS), 
 
1249
                  i, el, id;
 
1250
 
 
1251
        // Add the default value as a key for each element for easier lookup
 
1252
        for (i in this.ID) {
 
1253
            if (lang.hasOwnProperty(this.ID, i)) {
 
1254
                ids[this.ID[i]] = ids[i];
 
1255
            }
 
1256
        }
 
1257
 
 
1258
        // Check for picker element, if not there, create all of them
 
1259
        el = Dom.get(ids[this.ID.PICKER_BG]);
 
1260
        if (!el) {
 
1261
            _createElements.call(this);
 
1262
        } else {
 
1263
            this.logger.log("Using pre-existing markup");
 
1264
        }
 
1265
 
 
1266
        for (i in ids) {
 
1267
            if (lang.hasOwnProperty(ids, i)) {
 
1268
                // look for element
 
1269
                el = Dom.get(ids[i]);
 
1270
 
 
1271
                // generate an id if the implementer passed in an element reference,
 
1272
                // and the element did not have an id already
 
1273
                id = Dom.generateId(el);
 
1274
 
 
1275
                // update the id in case we generated the id
 
1276
                ids[i] = id; // key is WEBSAFE_SWATCH
 
1277
                ids[ids[i]] = id; // key is websafe_swatch
 
1278
 
 
1279
                // store the dom ref
 
1280
                els[id] = el;
 
1281
            }
 
1282
        }
 
1283
 
 
1284
        // set the initial visibility state of our controls
 
1285
            els = [o.SHOW_CONTROLS, 
 
1286
                   o.SHOW_RGB_CONTROLS,
 
1287
                   o.SHOW_HSV_CONTROLS,
 
1288
                   o.SHOW_HEX_CONTROLS,
 
1289
                   o.SHOW_HEX_SUMMARY,
 
1290
                   o.SHOW_WEBSAFE
 
1291
                   ];
 
1292
 
 
1293
        for (i=0; i<els.length; i=i+1) {
 
1294
            this.set(els[i], this.get(els[i]));
 
1295
        }
 
1296
 
 
1297
        var s = this.get(o.PICKER_SIZE);
 
1298
        this.logger.log("picker size" + s);
 
1299
 
 
1300
        this.hueSlider = Slider.getVertSlider(this.getElement(this.ID.HUE_BG), 
 
1301
                                              this.getElement(this.ID.HUE_THUMB), 0, s);
 
1302
        this.hueSlider.subscribe("change", _onHueSliderChange, this, true);
 
1303
 
 
1304
        this.pickerSlider = Slider.getSliderRegion(this.getElement(this.ID.PICKER_BG), 
 
1305
                                                   this.getElement(this.ID.PICKER_THUMB), 0, s, 0, s);
 
1306
        this.pickerSlider.subscribe("change", _onPickerSliderChange, this, true);
 
1307
 
 
1308
        // Set the animate state
 
1309
        this.set(o.ANIMATE,this.get(o.ANIMATE));
 
1310
 
 
1311
        //_onHueSliderChange.call(this, 0);
 
1312
 
 
1313
        Event.on(this.getElement(this.ID.WEBSAFE_SWATCH), "click", function(e) {
 
1314
               this.setValue(this.get(o.WEBSAFE));
 
1315
               //_updateSliders
 
1316
           }, this, true);
 
1317
 
 
1318
        Event.on(this.getElement(this.ID.CONTROLS_LABEL), "click", function(e) {
 
1319
               this.set(o.SHOW_CONTROLS, !this.get(o.SHOW_CONTROLS));
 
1320
               Event.preventDefault(e);
 
1321
           }, this, true);
 
1322
 
 
1323
        _attachRGBHSV.call(this, this.ID.R, this.OPT.RED); 
 
1324
        _attachRGBHSV.call(this, this.ID.G, this.OPT.GREEN); 
 
1325
        _attachRGBHSV.call(this, this.ID.B, this.OPT.BLUE); 
 
1326
        _attachRGBHSV.call(this, this.ID.H, this.OPT.HUE); 
 
1327
        _attachRGBHSV.call(this, this.ID.S, this.OPT.SATURATION); 
 
1328
        _attachRGBHSV.call(this, this.ID.V, this.OPT.VALUE); 
 
1329
 
 
1330
        Event.on(this.getElement(this.ID.HEX), "keydown", function(e, me) {
 
1331
                _hexFieldKeypress.call(me, e, this, me.OPT.HEX);
 
1332
            }, this);
 
1333
 
 
1334
        Event.on(this.getElement(this.ID.HEX), "keypress", _hexOnly, this);
 
1335
        Event.on(this.getElement(this.ID.HEX), "blur", function(e, me) {
 
1336
                _useFieldValue.call(me, e, this, me.OPT.HEX);
 
1337
            }, this);
 
1338
 
 
1339
        _updateRGB.call(this);
 
1340
    };
 
1341
 
 
1342
 
 
1343
    /**
 
1344
     * Updates the RGB values from the current state of the HSV
 
1345
     * values.  Executed when the one of the HSV form fields are
 
1346
     * updated
 
1347
     * _updateRGBFromHSV
 
1348
     * @private
 
1349
     */
 
1350
    var _updateRGBFromHSV = function() {
 
1351
        var hsv = [this.get(this.OPT.HUE), 
 
1352
                   this.get(this.OPT.SATURATION)/100,
 
1353
                   this.get(this.OPT.VALUE)/100];
 
1354
 
 
1355
        var rgb = Color.hsv2rgb(hsv);
 
1356
 
 
1357
        this.logger.log("HSV converted to RGB " + hsv + " : " + rgb);
 
1358
        this.set(this.OPT.RGB, rgb);
 
1359
 
 
1360
        _updateSliders.call(this);
 
1361
    };
 
1362
 
 
1363
    /**
 
1364
     * Parses the hex string to normalize shorthand values, converts
 
1365
     * the hex value to rgb and updates the rgb attribute (which
 
1366
     * updates the state for all of the other values)
 
1367
     * method _updateHex
 
1368
     * @private
 
1369
     */
 
1370
    var _updateHex = function() {
 
1371
       
 
1372
        var hex = this.get(this.OPT.HEX), l=hex.length;
 
1373
 
 
1374
        // support #369 -> #336699 shorthand
 
1375
        if (l === 3) {
 
1376
            var c = hex.split(""), i;
 
1377
            for (i=0; i<l; i=i+1) {
 
1378
                c[i] = c[i] + c[i];
 
1379
            }
 
1380
 
 
1381
            hex = c.join("");
 
1382
        }
 
1383
 
 
1384
        if (hex.length !== 6) {
 
1385
            this.logger.log(this.get(this.TXT.ILLEGAL_HEX), "error");
 
1386
            return false;
 
1387
        }
 
1388
 
 
1389
        var rgb = Color.hex2rgb(hex);
 
1390
 
 
1391
        this.logger.log(sub("Hex value set to {hex} ({rgb})", {
 
1392
                hex: hex, rgb: rgb
 
1393
            }));
 
1394
 
 
1395
        this.setValue(rgb);
 
1396
 
 
1397
        //_updateSliders.call(this);
 
1398
 
 
1399
    };
 
1400
 
 
1401
 
 
1402
 
 
1403
    /**
 
1404
     * Sets up the config attributes and the change listeners for this
 
1405
     * properties
 
1406
     * @method initAttributes
 
1407
     * @param attr An object containing default attribute values
 
1408
     */
 
1409
    proto.initAttributes = function(attr) {
 
1410
 
 
1411
        attr = attr || {};
 
1412
        YAHOO.widget.ColorPicker.superclass.initAttributes.call(this, attr);
 
1413
        
 
1414
        /**
 
1415
         * The size of the picker. Trying to change this is not recommended.
 
1416
         * @attribute pickersize
 
1417
         * @default 180
 
1418
         * @type int
 
1419
         */
 
1420
        this.setAttributeConfig(this.OPT.PICKER_SIZE, {
 
1421
                value: attr.size || this.DEFAULT.PICKER_SIZE
 
1422
            });
 
1423
 
 
1424
        /**
 
1425
         * The current hue value 0-360
 
1426
         * @attribute hue
 
1427
         * @type int
 
1428
         */
 
1429
        this.setAttributeConfig(this.OPT.HUE, {
 
1430
                value: attr.hue || 0,
 
1431
                validator: lang.isNumber
 
1432
            });
 
1433
 
 
1434
        /**
 
1435
         * The current saturation value 0-100
 
1436
         * @attribute saturation
 
1437
         * @type int
 
1438
         */
 
1439
        this.setAttributeConfig(this.OPT.SATURATION, {
 
1440
                value: attr.saturation || 0,
 
1441
                validator: lang.isNumber
 
1442
            });
 
1443
 
 
1444
        /**
 
1445
         * The current value/brightness value 0-100
 
1446
         * @attribute value
 
1447
         * @type int
 
1448
         */
 
1449
        this.setAttributeConfig(this.OPT.VALUE, {
 
1450
                value: lang.isNumber(attr.value) ? attr.value : 100,
 
1451
                validator: lang.isNumber
 
1452
            });
 
1453
 
 
1454
        /**
 
1455
         * The current red value 0-255
 
1456
         * @attribute red
 
1457
         * @type int
 
1458
         */
 
1459
        this.setAttributeConfig(this.OPT.RED, {
 
1460
                value: lang.isNumber(attr.red) ? attr.red : 255,
 
1461
                validator: lang.isNumber
 
1462
            });
 
1463
 
 
1464
        /**
 
1465
         * The current green value 0-255
 
1466
         * @attribute green 
 
1467
         * @type int
 
1468
         */
 
1469
        this.setAttributeConfig(this.OPT.GREEN, {
 
1470
                value: lang.isNumber(attr.green) ? attr.green : 255,
 
1471
                validator: lang.isNumber
 
1472
            });
 
1473
 
 
1474
        /**
 
1475
         * The current blue value 0-255
 
1476
         * @attribute blue
 
1477
         * @type int
 
1478
         */
 
1479
        this.setAttributeConfig(this.OPT.BLUE, {
 
1480
                value: lang.isNumber(attr.blue) ? attr.blue : 255,
 
1481
                validator: lang.isNumber
 
1482
            });
 
1483
 
 
1484
        /**
 
1485
         * The current hex value #000000-#FFFFFF, without the #
 
1486
         * @attribute hex
 
1487
         * @type string
 
1488
         */
 
1489
        this.setAttributeConfig(this.OPT.HEX, {
 
1490
                value: attr.hex || "FFFFFF",
 
1491
                validator: lang.isString
 
1492
            });
 
1493
 
 
1494
        /**
 
1495
         * The current rgb value.  Updates the state of all of the
 
1496
         * other value fields.  Read-only: use setValue to set the
 
1497
         * controls rgb value.
 
1498
         * @attribute hex
 
1499
         * @type [int, int, int]
 
1500
         * @readonly
 
1501
         */
 
1502
        this.setAttributeConfig(this.OPT.RGB, {
 
1503
                value: attr.rgb || [255,255,255],
 
1504
                method: function(rgb) {
 
1505
 
 
1506
                    this.set(this.OPT.RED, rgb[0], true);
 
1507
                    this.set(this.OPT.GREEN, rgb[1], true);
 
1508
                    this.set(this.OPT.BLUE, rgb[2], true);
 
1509
 
 
1510
                    var websafe = Color.websafe(rgb);
 
1511
                    this.set(this.OPT.WEBSAFE, websafe, true);
 
1512
 
 
1513
                    var hex = Color.rgb2hex(rgb);
 
1514
                    this.set(this.OPT.HEX, hex, true);
 
1515
 
 
1516
                    var hsv = Color.rgb2hsv(rgb);
 
1517
 
 
1518
                    this.logger.log(sub("RGB value set to {rgb} (hsv: {hsv})", {
 
1519
                            "hsv": hsv, "rgb": rgb
 
1520
                        }));
 
1521
 
 
1522
                    this.set(this.OPT.HUE, hsv[0], true);
 
1523
                    this.set(this.OPT.SATURATION, Math.round(hsv[1]*100), true);
 
1524
                    this.set(this.OPT.VALUE, Math.round(hsv[2]*100), true);
 
1525
                },
 
1526
                readonly: true
 
1527
            });
 
1528
 
 
1529
        /**
 
1530
         * If the color picker will live inside of a container object,
 
1531
         * set, provide a reference to it so the control can use the
 
1532
         * container's events.
 
1533
         * @attribute container
 
1534
         * @type YAHOO.widget.Panel
 
1535
         */
 
1536
        this.setAttributeConfig(this.OPT.CONTAINER, {
 
1537
                    value: null,
 
1538
                    method: function(container) {
 
1539
                        if (container) {
 
1540
                            // Position can get out of sync when the
 
1541
                            // control is manipulated while display is
 
1542
                            // none.  Resetting the slider constraints
 
1543
                            // when it is visible gets the state back in
 
1544
                            // order.
 
1545
                            container.showEvent.subscribe(function() {
 
1546
                                // this.pickerSlider.thumb.resetConstraints();
 
1547
                                // this.hueSlider.thumb.resetConstraints();
 
1548
                                this.pickerSlider.focus();
 
1549
                            }, this, true);
 
1550
                        }
 
1551
                    }
 
1552
                });
 
1553
        /**
 
1554
         * The closest current websafe value
 
1555
         * @attribute websafe
 
1556
         * @type int
 
1557
         */
 
1558
        this.setAttributeConfig(this.OPT.WEBSAFE, {
 
1559
                value: attr.websafe || [255,255,255]
 
1560
            });
 
1561
 
 
1562
 
 
1563
        var ids = attr.ids || lang.merge({}, this.ID);
 
1564
 
 
1565
        if (!attr.ids && _pickercount > 1) {
 
1566
            for (var i in ids) {
 
1567
                if (lang.hasOwnProperty(ids, i)) {
 
1568
                    ids[i] = ids[i] + _pickercount;
 
1569
                }
 
1570
            }
 
1571
        }
 
1572
 
 
1573
 
 
1574
        /**
 
1575
         * A list of element ids and/or element references used by the 
 
1576
         * control.  The default is the this.ID list, and can be customized
 
1577
         * by passing a list in the contructor
 
1578
         * @attribute ids
 
1579
         * @type {referenceid: realid}
 
1580
         * @writeonce
 
1581
         */
 
1582
        this.setAttributeConfig(this.OPT.IDS, {
 
1583
                value: ids,
 
1584
                writeonce: true
 
1585
            });
 
1586
 
 
1587
        /**
 
1588
         * A list of txt strings for internationalization.  Default
 
1589
         * is this.TXT
 
1590
         * @attribute txt
 
1591
         * @type {key: txt}
 
1592
         * @writeonce
 
1593
         */
 
1594
        this.setAttributeConfig(this.OPT.TXT, {
 
1595
                value: attr.txt || this.TXT,
 
1596
                writeonce: true
 
1597
            });
 
1598
 
 
1599
        /**
 
1600
         * The img src default list
 
1601
         * is this.IMAGES
 
1602
         * @attribute images
 
1603
         * @type {key: image}
 
1604
         * @writeonce
 
1605
         */
 
1606
        this.setAttributeConfig(this.OPT.IMAGES, {
 
1607
                value: attr.images || this.IMAGE,
 
1608
                writeonce: true
 
1609
            });
 
1610
        /**
 
1611
         * The element refs used by this control.  Set at initialization
 
1612
         * @attribute elements
 
1613
         * @type {id: HTMLElement}
 
1614
         * @readonly
 
1615
         */
 
1616
        this.setAttributeConfig(this.OPT.ELEMENTS, {
 
1617
                value: {},
 
1618
                readonly: true
 
1619
            });
 
1620
 
 
1621
        /**
 
1622
         * Returns the cached element reference.  If the id is not a string, it
 
1623
         * is assumed that it is an element and this is returned.
 
1624
         * @param id {string|HTMLElement} the element key, id, or ref
 
1625
         * @param on {boolean} hide or show.  If true, show
 
1626
         * @private */
 
1627
        var _hideShowEl = function(id, on) {
 
1628
            var el = (lang.isString(id) ? this.getElement(id) : id);
 
1629
            //Dom.setStyle(id, "visibility", (on) ? "" : "hidden");
 
1630
            Dom.setStyle(el, "display", (on) ? "" : "none");
 
1631
        };
 
1632
 
 
1633
        /**
 
1634
         * Hide/show the entire set of controls
 
1635
         * @attribute showcontrols
 
1636
         * @type boolean
 
1637
         * @default true
 
1638
         */
 
1639
        this.setAttributeConfig(this.OPT.SHOW_CONTROLS, {
 
1640
                value: lang.isBoolean(attr.showcontrols) ? attr.showcontrols : true,
 
1641
                method: function(on) {
 
1642
 
 
1643
                    var el = Dom.getElementsByClassName("bd", "div", 
 
1644
                            this.getElement(this.ID.CONTROLS))[0];
 
1645
 
 
1646
                    _hideShowEl.call(this, el, on);
 
1647
 
 
1648
                    this.getElement(this.ID.CONTROLS_LABEL).innerHTML = 
 
1649
                        (on) ? this.get(this.OPT.TXT).HIDE_CONTROLS :
 
1650
                               this.get(this.OPT.TXT).SHOW_CONTROLS;
 
1651
 
 
1652
                }
 
1653
            });
 
1654
 
 
1655
        /**
 
1656
         * Hide/show the rgb controls
 
1657
         * @attribute showrgbcontrols
 
1658
         * @type boolean
 
1659
         * @default true
 
1660
         */
 
1661
        this.setAttributeConfig(this.OPT.SHOW_RGB_CONTROLS, {
 
1662
                value: lang.isBoolean(attr.showrgbcontrols) ? attr.showrgbcontrols : true,
 
1663
                method: function(on) {
 
1664
                    //Dom.setStyle(this.getElement(this.ID.RBG_CONTROLS), "visibility", (on) ? "" : "hidden");
 
1665
                    _hideShowEl.call(this, this.ID.RGB_CONTROLS, on);
 
1666
                }
 
1667
            });
 
1668
 
 
1669
        /**
 
1670
         * Hide/show the hsv controls
 
1671
         * @attribute showhsvcontrols
 
1672
         * @type boolean
 
1673
         * @default false
 
1674
         */
 
1675
        this.setAttributeConfig(this.OPT.SHOW_HSV_CONTROLS, {
 
1676
                value: lang.isBoolean(attr.showhsvcontrols) ?
 
1677
                                      attr.showhsvcontrols : false,
 
1678
                method: function(on) {
 
1679
                    //Dom.setStyle(this.getElement(this.ID.HSV_CONTROLS), "visibility", (on) ? "" : "hidden");
 
1680
                    _hideShowEl.call(this, this.ID.HSV_CONTROLS, on);
 
1681
 
 
1682
                    // can't show both the hsv controls and the rbg hex summary
 
1683
                    if (on && this.get(this.OPT.SHOW_HEX_SUMMARY)) {
 
1684
                        this.set(this.OPT.SHOW_HEX_SUMMARY, false);
 
1685
                    }
 
1686
                }
 
1687
            });
 
1688
 
 
1689
        /**
 
1690
         * Hide/show the hex controls
 
1691
         * @attribute showhexcontrols
 
1692
         * @type boolean
 
1693
         * @default true
 
1694
         */
 
1695
        this.setAttributeConfig(this.OPT.SHOW_HEX_CONTROLS, {
 
1696
                value: lang.isBoolean(attr.showhexcontrols) ?
 
1697
                                      attr.showhexcontrols : false,
 
1698
                method: function(on) {
 
1699
                    _hideShowEl.call(this, this.ID.HEX_CONTROLS, on);
 
1700
                }
 
1701
            });
 
1702
 
 
1703
        /**
 
1704
         * Hide/show the websafe swatch
 
1705
         * @attribute showwebsafe
 
1706
         * @type boolean
 
1707
         * @default true
 
1708
         */
 
1709
        this.setAttributeConfig(this.OPT.SHOW_WEBSAFE, {
 
1710
                value: lang.isBoolean(attr.showwebsafe) ? attr.showwebsafe : true,
 
1711
                method: function(on) {
 
1712
                    _hideShowEl.call(this, this.ID.WEBSAFE_SWATCH, on);
 
1713
                }
 
1714
            });
 
1715
 
 
1716
        /**
 
1717
         * Hide/show the hex summary
 
1718
         * @attribute showhexsummary
 
1719
         * @type boolean
 
1720
         * @default true
 
1721
         */
 
1722
        this.setAttributeConfig(this.OPT.SHOW_HEX_SUMMARY, {
 
1723
                value: lang.isBoolean(attr.showhexsummary) ? attr.showhexsummary : true,
 
1724
                method: function(on) {
 
1725
                    _hideShowEl.call(this, this.ID.HEX_SUMMARY, on);
 
1726
 
 
1727
                    // can't show both the hsv controls and the rbg hex summary
 
1728
                    if (on && this.get(this.OPT.SHOW_HSV_CONTROLS)) {
 
1729
                        this.set(this.OPT.SHOW_HSV_CONTROLS, false);
 
1730
                    }
 
1731
                }
 
1732
            });
 
1733
        this.setAttributeConfig(this.OPT.ANIMATE, {
 
1734
                value: lang.isBoolean(attr.animate) ? attr.animate : true,
 
1735
                method: function(on) {
 
1736
                    this.pickerSlider.animate = on;
 
1737
                    this.hueSlider.animate = on;
 
1738
                }
 
1739
            });
 
1740
 
 
1741
        this.on(this.OPT.HUE + "Change", _updateRGBFromHSV, this, true);
 
1742
        this.on(this.OPT.SATURATION + "Change", _updateRGBFromHSV, this, true);
 
1743
        this.on(this.OPT.VALUE + "Change", _updatePickerSlider, this, true);
 
1744
 
 
1745
        this.on(this.OPT.RED + "Change", _updateRGB, this, true);
 
1746
        this.on(this.OPT.GREEN + "Change", _updateRGB, this, true);
 
1747
        this.on(this.OPT.BLUE + "Change", _updateRGB, this, true);
 
1748
 
 
1749
        this.on(this.OPT.HEX + "Change", _updateHex, this, true);
 
1750
 
 
1751
        this.initPicker();
 
1752
    };
 
1753
 
 
1754
})();
 
1755
YAHOO.register("colorpicker", YAHOO.widget.ColorPicker, {version: "2.6.0", build: "1321"});