source: extensions/photoWidget/js/colorpicker.js @ 7830

Last change on this file since 7830 was 5611, checked in by nikrou, 14 years ago

New plugin photoWidget : first public release

File size: 16.8 KB
Line 
1/**
2 *
3 * Color picker
4 * Author: Stefan Petre www.eyecon.ro
5 *
6 * Dual licensed under the MIT and GPL licenses
7 *
8 */
9(function ($) {
10        var ColorPicker = function () {
11                var
12                        ids = {},
13                        inAction,
14                        charMin = 65,
15                        visible,
16                        tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
17                        defaults = {
18                                eventName: 'click',
19                                onShow: function () {},
20                                onBeforeShow: function(){},
21                                onHide: function () {},
22                                onChange: function () {},
23                                onSubmit: function () {},
24                                color: 'ff0000',
25                                livePreview: true,
26                                flat: false
27                        },
28                        fillRGBFields = function  (hsb, cal) {
29                                var rgb = HSBToRGB(hsb);
30                                $(cal).data('colorpicker').fields
31                                        .eq(1).val(rgb.r).end()
32                                        .eq(2).val(rgb.g).end()
33                                        .eq(3).val(rgb.b).end();
34                        },
35                        fillHSBFields = function  (hsb, cal) {
36                                $(cal).data('colorpicker').fields
37                                        .eq(4).val(hsb.h).end()
38                                        .eq(5).val(hsb.s).end()
39                                        .eq(6).val(hsb.b).end();
40                        },
41                        fillHexFields = function (hsb, cal) {
42                                $(cal).data('colorpicker').fields
43                                        .eq(0).val(HSBToHex(hsb)).end();
44                        },
45                        setSelector = function (hsb, cal) {
46                                $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
47                                $(cal).data('colorpicker').selectorIndic.css({
48                                        left: parseInt(150 * hsb.s/100, 10),
49                                        top: parseInt(150 * (100-hsb.b)/100, 10)
50                                });
51                        },
52                        setHue = function (hsb, cal) {
53                                $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
54                        },
55                        setCurrentColor = function (hsb, cal) {
56                                $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
57                        },
58                        setNewColor = function (hsb, cal) {
59                                $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
60                        },
61                        keyDown = function (ev) {
62                                var pressedKey = ev.charCode || ev.keyCode || -1;
63                                if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
64                                        return false;
65                                }
66                                var cal = $(this).parent().parent();
67                                if (cal.data('colorpicker').livePreview === true) {
68                                        change.apply(this);
69                                }
70                        },
71                        change = function (ev) {
72                                var cal = $(this).parent().parent(), col;
73                                if (this.parentNode.className.indexOf('_hex') > 0) {
74                                        cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
75                                } else if (this.parentNode.className.indexOf('_hsb') > 0) {
76                                        cal.data('colorpicker').color = col = fixHSB({
77                                                h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
78                                                s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
79                                                b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
80                                        });
81                                } else {
82                                        cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
83                                                r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
84                                                g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
85                                                b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
86                                        }));
87                                }
88                                if (ev) {
89                                        fillRGBFields(col, cal.get(0));
90                                        fillHexFields(col, cal.get(0));
91                                        fillHSBFields(col, cal.get(0));
92                                }
93                                setSelector(col, cal.get(0));
94                                setHue(col, cal.get(0));
95                                setNewColor(col, cal.get(0));
96                                cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
97                        },
98                        blur = function (ev) {
99                                var cal = $(this).parent().parent();
100                                cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');
101                        },
102                        focus = function () {
103                                charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
104                                $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
105                                $(this).parent().addClass('colorpicker_focus');
106                        },
107                        downIncrement = function (ev) {
108                                var field = $(this).parent().find('input').focus();
109                                var current = {
110                                        el: $(this).parent().addClass('colorpicker_slider'),
111                                        max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
112                                        y: ev.pageY,
113                                        field: field,
114                                        val: parseInt(field.val(), 10),
115                                        preview: $(this).parent().parent().data('colorpicker').livePreview                                     
116                                };
117                                $(document).bind('mouseup', current, upIncrement);
118                                $(document).bind('mousemove', current, moveIncrement);
119                        },
120                        moveIncrement = function (ev) {
121                                ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
122                                if (ev.data.preview) {
123                                        change.apply(ev.data.field.get(0), [true]);
124                                }
125                                return false;
126                        },
127                        upIncrement = function (ev) {
128                                change.apply(ev.data.field.get(0), [true]);
129                                ev.data.el.removeClass('colorpicker_slider').find('input').focus();
130                                $(document).unbind('mouseup', upIncrement);
131                                $(document).unbind('mousemove', moveIncrement);
132                                return false;
133                        },
134                        downHue = function (ev) {
135                                var current = {
136                                        cal: $(this).parent(),
137                                        y: $(this).offset().top
138                                };
139                                current.preview = current.cal.data('colorpicker').livePreview;
140                                $(document).bind('mouseup', current, upHue);
141                                $(document).bind('mousemove', current, moveHue);
142                        },
143                        moveHue = function (ev) {
144                                change.apply(
145                                        ev.data.cal.data('colorpicker')
146                                                .fields
147                                                .eq(4)
148                                                .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
149                                                .get(0),
150                                        [ev.data.preview]
151                                );
152                                return false;
153                        },
154                        upHue = function (ev) {
155                                fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
156                                fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
157                                $(document).unbind('mouseup', upHue);
158                                $(document).unbind('mousemove', moveHue);
159                                return false;
160                        },
161                        downSelector = function (ev) {
162                                var current = {
163                                        cal: $(this).parent(),
164                                        pos: $(this).offset()
165                                };
166                                current.preview = current.cal.data('colorpicker').livePreview;
167                                $(document).bind('mouseup', current, upSelector);
168                                $(document).bind('mousemove', current, moveSelector);
169                        },
170                        moveSelector = function (ev) {
171                                change.apply(
172                                        ev.data.cal.data('colorpicker')
173                                                .fields
174                                                .eq(6)
175                                                .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
176                                                .end()
177                                                .eq(5)
178                                                .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
179                                                .get(0),
180                                        [ev.data.preview]
181                                );
182                                return false;
183                        },
184                        upSelector = function (ev) {
185                                fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
186                                fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
187                                $(document).unbind('mouseup', upSelector);
188                                $(document).unbind('mousemove', moveSelector);
189                                return false;
190                        },
191                        enterSubmit = function (ev) {
192                                $(this).addClass('colorpicker_focus');
193                        },
194                        leaveSubmit = function (ev) {
195                                $(this).removeClass('colorpicker_focus');
196                        },
197                        clickSubmit = function (ev) {
198                                var cal = $(this).parent();
199                                var col = cal.data('colorpicker').color;
200                                cal.data('colorpicker').origColor = col;
201                                setCurrentColor(col, cal.get(0));
202                                cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);
203                        },
204                        show = function (ev) {
205                                var cal = $('#' + $(this).data('colorpickerId'));
206                                cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
207                                var pos = $(this).offset();
208                                var viewPort = getViewport();
209                                var top = pos.top + this.offsetHeight;
210                                var left = pos.left;
211                                if (top + 176 > viewPort.t + viewPort.h) {
212                                        top -= this.offsetHeight + 176;
213                                }
214                                if (left + 356 > viewPort.l + viewPort.w) {
215                                        left -= 356;
216                                }
217                                cal.css({left: left + 'px', top: top + 'px'});
218                                if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
219                                        cal.show();
220                                }
221                                $(document).bind('mousedown', {cal: cal}, hide);
222                                return false;
223                        },
224                        hide = function (ev) {
225                                if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
226                                        if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
227                                                ev.data.cal.hide();
228                                        }
229                                        $(document).unbind('mousedown', hide);
230                                }
231                        },
232                        isChildOf = function(parentEl, el, container) {
233                                if (parentEl == el) {
234                                        return true;
235                                }
236                                if (parentEl.contains) {
237                                        return parentEl.contains(el);
238                                }
239                                if ( parentEl.compareDocumentPosition ) {
240                                        return !!(parentEl.compareDocumentPosition(el) & 16);
241                                }
242                                var prEl = el.parentNode;
243                                while(prEl && prEl != container) {
244                                        if (prEl == parentEl)
245                                                return true;
246                                        prEl = prEl.parentNode;
247                                }
248                                return false;
249                        },
250                        getViewport = function () {
251                                var m = document.compatMode == 'CSS1Compat';
252                                return {
253                                        l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
254                                        t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
255                                        w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
256                                        h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
257                                };
258                        },
259                        fixHSB = function (hsb) {
260                                return {
261                                        h: Math.min(360, Math.max(0, hsb.h)),
262                                        s: Math.min(100, Math.max(0, hsb.s)),
263                                        b: Math.min(100, Math.max(0, hsb.b))
264                                };
265                        }, 
266                        fixRGB = function (rgb) {
267                                return {
268                                        r: Math.min(255, Math.max(0, rgb.r)),
269                                        g: Math.min(255, Math.max(0, rgb.g)),
270                                        b: Math.min(255, Math.max(0, rgb.b))
271                                };
272                        },
273                        fixHex = function (hex) {
274                                var len = 6 - hex.length;
275                                if (len > 0) {
276                                        var o = [];
277                                        for (var i=0; i<len; i++) {
278                                                o.push('0');
279                                        }
280                                        o.push(hex);
281                                        hex = o.join('');
282                                }
283                                return hex;
284                        }, 
285                        HexToRGB = function (hex) {
286                                var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
287                                return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
288                        },
289                        HexToHSB = function (hex) {
290                                return RGBToHSB(HexToRGB(hex));
291                        },
292                        RGBToHSB = function (rgb) {
293                                var hsb = {
294                                        h: 0,
295                                        s: 0,
296                                        b: 0
297                                };
298                                var min = Math.min(rgb.r, rgb.g, rgb.b);
299                                var max = Math.max(rgb.r, rgb.g, rgb.b);
300                                var delta = max - min;
301                                hsb.b = max;
302                                if (max != 0) {
303                                       
304                                }
305                                hsb.s = max != 0 ? 255 * delta / max : 0;
306                                if (hsb.s != 0) {
307                                        if (rgb.r == max) {
308                                                hsb.h = (rgb.g - rgb.b) / delta;
309                                        } else if (rgb.g == max) {
310                                                hsb.h = 2 + (rgb.b - rgb.r) / delta;
311                                        } else {
312                                                hsb.h = 4 + (rgb.r - rgb.g) / delta;
313                                        }
314                                } else {
315                                        hsb.h = -1;
316                                }
317                                hsb.h *= 60;
318                                if (hsb.h < 0) {
319                                        hsb.h += 360;
320                                }
321                                hsb.s *= 100/255;
322                                hsb.b *= 100/255;
323                                return hsb;
324                        },
325                        HSBToRGB = function (hsb) {
326                                var rgb = {};
327                                var h = Math.round(hsb.h);
328                                var s = Math.round(hsb.s*255/100);
329                                var v = Math.round(hsb.b*255/100);
330                                if(s == 0) {
331                                        rgb.r = rgb.g = rgb.b = v;
332                                } else {
333                                        var t1 = v;
334                                        var t2 = (255-s)*v/255;
335                                        var t3 = (t1-t2)*(h%60)/60;
336                                        if(h==360) h = 0;
337                                        if(h<60) {rgb.r=t1;     rgb.b=t2; rgb.g=t2+t3}
338                                        else if(h<120) {rgb.g=t1; rgb.b=t2;     rgb.r=t1-t3}
339                                        else if(h<180) {rgb.g=t1; rgb.r=t2;     rgb.b=t2+t3}
340                                        else if(h<240) {rgb.b=t1; rgb.r=t2;     rgb.g=t1-t3}
341                                        else if(h<300) {rgb.b=t1; rgb.g=t2;     rgb.r=t2+t3}
342                                        else if(h<360) {rgb.r=t1; rgb.g=t2;     rgb.b=t1-t3}
343                                        else {rgb.r=0; rgb.g=0; rgb.b=0}
344                                }
345                                return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
346                        },
347                        RGBToHex = function (rgb) {
348                                var hex = [
349                                        rgb.r.toString(16),
350                                        rgb.g.toString(16),
351                                        rgb.b.toString(16)
352                                ];
353                                $.each(hex, function (nr, val) {
354                                        if (val.length == 1) {
355                                                hex[nr] = '0' + val;
356                                        }
357                                });
358                                return hex.join('');
359                        },
360                        HSBToHex = function (hsb) {
361                                return RGBToHex(HSBToRGB(hsb));
362                        },
363                        restoreOriginal = function () {
364                                var cal = $(this).parent();
365                                var col = cal.data('colorpicker').origColor;
366                                cal.data('colorpicker').color = col;
367                                fillRGBFields(col, cal.get(0));
368                                fillHexFields(col, cal.get(0));
369                                fillHSBFields(col, cal.get(0));
370                                setSelector(col, cal.get(0));
371                                setHue(col, cal.get(0));
372                                setNewColor(col, cal.get(0));
373                        };
374                return {
375                        init: function (opt) {
376                                opt = $.extend({}, defaults, opt||{});
377                                if (typeof opt.color == 'string') {
378                                        opt.color = HexToHSB(opt.color);
379                                } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {
380                                        opt.color = RGBToHSB(opt.color);
381                                } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {
382                                        opt.color = fixHSB(opt.color);
383                                } else {
384                                        return this;
385                                }
386                                return this.each(function () {
387                                        if (!$(this).data('colorpickerId')) {
388                                                var options = $.extend({}, opt);
389                                                options.origColor = opt.color;
390                                                var id = 'collorpicker_' + parseInt(Math.random() * 1000);
391                                                $(this).data('colorpickerId', id);
392                                                var cal = $(tpl).attr('id', id);
393                                                if (options.flat) {
394                                                        cal.appendTo(this).show();
395                                                } else {
396                                                        cal.appendTo(document.body);
397                                                }
398                                                options.fields = cal
399                                                                                        .find('input')
400                                                                                                .bind('keyup', keyDown)
401                                                                                                .bind('change', change)
402                                                                                                .bind('blur', blur)
403                                                                                                .bind('focus', focus);
404                                                cal
405                                                        .find('span').bind('mousedown', downIncrement).end()
406                                                        .find('>div.colorpicker_current_color').bind('click', restoreOriginal);
407                                                options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
408                                                options.selectorIndic = options.selector.find('div div');
409                                                options.el = this;
410                                                options.hue = cal.find('div.colorpicker_hue div');
411                                                cal.find('div.colorpicker_hue').bind('mousedown', downHue);
412                                                options.newColor = cal.find('div.colorpicker_new_color');
413                                                options.currentColor = cal.find('div.colorpicker_current_color');
414                                                cal.data('colorpicker', options);
415                                                cal.find('div.colorpicker_submit')
416                                                        .bind('mouseenter', enterSubmit)
417                                                        .bind('mouseleave', leaveSubmit)
418                                                        .bind('click', clickSubmit);
419                                                fillRGBFields(options.color, cal.get(0));
420                                                fillHSBFields(options.color, cal.get(0));
421                                                fillHexFields(options.color, cal.get(0));
422                                                setHue(options.color, cal.get(0));
423                                                setSelector(options.color, cal.get(0));
424                                                setCurrentColor(options.color, cal.get(0));
425                                                setNewColor(options.color, cal.get(0));
426                                                if (options.flat) {
427                                                        cal.css({
428                                                                position: 'relative',
429                                                                display: 'block'
430                                                        });
431                                                } else {
432                                                        $(this).bind(options.eventName, show);
433                                                }
434                                        }
435                                });
436                        },
437                        showPicker: function() {
438                                return this.each( function () {
439                                        if ($(this).data('colorpickerId')) {
440                                                show.apply(this);
441                                        }
442                                });
443                        },
444                        hidePicker: function() {
445                                return this.each( function () {
446                                        if ($(this).data('colorpickerId')) {
447                                                $('#' + $(this).data('colorpickerId')).hide();
448                                        }
449                                });
450                        },
451                        setColor: function(col) {
452                                if (typeof col == 'string') {
453                                        col = HexToHSB(col);
454                                } else if (col.r != undefined && col.g != undefined && col.b != undefined) {
455                                        col = RGBToHSB(col);
456                                } else if (col.h != undefined && col.s != undefined && col.b != undefined) {
457                                        col = fixHSB(col);
458                                } else {
459                                        return this;
460                                }
461                                return this.each(function(){
462                                        if ($(this).data('colorpickerId')) {
463                                                var cal = $('#' + $(this).data('colorpickerId'));
464                                                cal.data('colorpicker').color = col;
465                                                cal.data('colorpicker').origColor = col;
466                                                fillRGBFields(col, cal.get(0));
467                                                fillHSBFields(col, cal.get(0));
468                                                fillHexFields(col, cal.get(0));
469                                                setHue(col, cal.get(0));
470                                                setSelector(col, cal.get(0));
471                                                setCurrentColor(col, cal.get(0));
472                                                setNewColor(col, cal.get(0));
473                                        }
474                                });
475                        }
476                };
477        }();
478        $.fn.extend({
479                ColorPicker: ColorPicker.init,
480                ColorPickerHide: ColorPicker.hidePicker,
481                ColorPickerShow: ColorPicker.showPicker,
482                ColorPickerSetColor: ColorPicker.setColor
483        });
484})(jQuery)
Note: See TracBrowser for help on using the repository browser.