Dotclear

source: admin/js/jquery/jquery.farbtastic.js @ 0:54703be25dd6

Revision 0:54703be25dd6, 8.4 KB checked in by Dsls <dsls@…>, 14 years ago (diff)

2.3 branch (trunk) first checkin

Line 
1// $Id: farbtastic.js,v 1.2 2007/01/08 22:53:01 unconed Exp $
2// Farbtastic 1.2
3
4jQuery.fn.farbtastic = function (callback) {
5     $.farbtastic(this, callback);
6     return this;
7};
8
9jQuery.farbtastic = function (container, callback) {
10     var container = $(container).get(0);
11     return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
12};
13
14jQuery._farbtastic = function (container, callback) {
15     // Store farbtastic object
16     var fb = this;
17     
18     // Insert markup
19     $(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
20     var e = $('.farbtastic', container);
21     fb.wheel = $('.wheel', container).get(0);
22     // Dimensions
23     fb.radius = 84;
24     fb.square = 100;
25     fb.width = 194;
26     
27     // Fix background PNGs in IE6
28     if (navigator.appVersion.match(/MSIE [0-6]\./)) {
29          $('*', e).each(function () {
30               if (this.currentStyle.backgroundImage != 'none') {
31                    var image = this.currentStyle.backgroundImage;
32                    image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
33                    $(this).css({
34                         'backgroundImage': 'none',
35                         'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
36                    });
37               }
38          });
39     }
40
41     /**
42     * Link to the given element(s) or callback.
43     */
44     fb.linkTo = function (callback) {
45          // Unbind previous nodes
46          if (typeof fb.callback == 'object') {
47               $(fb.callback).unbind('keyup', fb.updateValue);
48          }
49         
50          // Reset color
51          fb.color = null;
52         
53          // Bind callback or elements
54          if (typeof callback == 'function') {
55               fb.callback = callback;
56          }
57          else if (typeof callback == 'object' || typeof callback == 'string') {
58               fb.callback = $(callback);
59               fb.callback.bind('keyup', fb.updateValue);
60               if (fb.callback.get(0).value) {
61                    fb.setColor(fb.callback.get(0).value);
62               }
63          }
64          return this;
65     };
66     
67     fb.updateValue = function (event) {
68          if (this.value && this.value != fb.color) {
69               fb.setColor(this.value);
70          }
71     };
72     
73     /**
74     * Change color with HTML syntax #123456
75     */
76     fb.setColor = function (color) {
77          var unpack = fb.unpack(color);
78          if (fb.color != color && unpack) {
79               fb.color = color;
80               fb.rgb = unpack;
81               fb.hsl = fb.RGBToHSL(fb.rgb);
82               fb.updateDisplay();
83          }
84          return this;
85     };
86     
87     /**
88     * Change color with HSL triplet [0..1, 0..1, 0..1]
89     */
90     fb.setHSL = function (hsl) {
91          fb.hsl = hsl;
92          fb.rgb = fb.HSLToRGB(hsl);
93          fb.color = fb.pack(fb.rgb);
94          fb.updateDisplay();
95          return this;
96     };
97     
98     /////////////////////////////////////////////////////
99     
100     /**
101     * Retrieve the coordinates of the given event relative to the center
102     * of the widget.
103     */
104     fb.widgetCoords = function (event) {
105          var x, y;
106          var el = event.target || event.srcElement;
107          var reference = fb.wheel;
108         
109          if (typeof event.offsetX != 'undefined') {
110               // Use offset coordinates and find common offsetParent
111               var pos = { x: event.offsetX, y: event.offsetY };
112               
113               // Send the coordinates upwards through the offsetParent chain.
114               var e = el;
115               while (e) {
116                    e.mouseX = pos.x;
117                    e.mouseY = pos.y;
118                    pos.x += e.offsetLeft;
119                    pos.y += e.offsetTop;
120                    e = e.offsetParent;
121               }
122               
123               // Look for the coordinates starting from the wheel widget.
124               var e = reference;
125               var offset = { x: 0, y: 0 };
126               while (e) {
127                    if (typeof e.mouseX != 'undefined') {
128                         x = e.mouseX - offset.x;
129                         y = e.mouseY - offset.y;
130                         break;
131                    }
132                    offset.x += e.offsetLeft;
133                    offset.y += e.offsetTop;
134                    e = e.offsetParent;
135               }
136               
137               // Reset stored coordinates
138               e = el;
139               while (e) {
140                    e.mouseX = undefined;
141                    e.mouseY = undefined;
142                    e = e.offsetParent;
143               }
144          }
145          else {
146          // Use absolute coordinates
147               var pos = fb.absolutePosition(reference);
148               x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
149               y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
150          }
151          // Subtract distance to middle
152          return { x: x - fb.width / 2, y: y - fb.width / 2 };
153     };
154     
155     /**
156     * Mousedown handler
157     */
158     fb.mousedown = function (event) {
159          // Capture mouse
160          if (!document.dragging) {
161               $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
162               document.dragging = true;
163          }
164         
165          // Check which area is being dragged
166          var pos = fb.widgetCoords(event);
167          fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
168         
169          // Process
170          fb.mousemove(event);
171          return false;
172     };
173     
174     /**
175     * Mousemove handler
176     */
177     fb.mousemove = function (event) {
178          // Get coordinates relative to color picker center
179          var pos = fb.widgetCoords(event);
180         
181          // Set new HSL parameters
182          if (fb.circleDrag) {
183               var hue = Math.atan2(pos.x, -pos.y) / 6.28;
184               if (hue < 0) hue += 1;
185               fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
186          }
187          else {
188               var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
189               var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
190               fb.setHSL([fb.hsl[0], sat, lum]);
191          }
192          return false;
193     };
194     
195     /**
196     * Mouseup handler
197     */
198     fb.mouseup = function () {
199          // Uncapture mouse
200          $(document).unbind('mousemove', fb.mousemove);
201          $(document).unbind('mouseup', fb.mouseup);
202          document.dragging = false;
203     };
204     
205     /**
206     * Update the markers and styles
207     */
208     fb.updateDisplay = function () {
209          // Markers
210          var angle = fb.hsl[0] * 6.28;
211          $('.h-marker', e).css({
212               left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
213               top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
214          });
215         
216          $('.sl-marker', e).css({
217               left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
218               top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
219          });
220         
221          // Saturation/Luminance gradient
222          $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
223         
224          // Linked elements or callback
225          if (typeof fb.callback == 'object') {
226               // Set background/foreground color
227               $(fb.callback).css({
228                    backgroundColor: fb.color,
229                    color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
230               });
231                   
232               // Change linked value
233               $(fb.callback).each(function() {
234                    if (this.value != fb.color) {
235                         this.value = fb.color;
236                    }
237               });
238               $(fb.callback).change();
239          }
240          else if (typeof fb.callback == 'function') {
241               fb.callback.call(fb, fb.color);
242          }
243     };
244     
245     /**
246     * Get absolute position of element
247     */
248     fb.absolutePosition = function (el) {
249          var r = { x: el.offsetLeft, y: el.offsetTop };
250          // Resolve relative to offsetParent
251          if (el.offsetParent) {
252               var tmp = fb.absolutePosition(el.offsetParent);
253               r.x += tmp.x;
254               r.y += tmp.y;
255          }
256          return r;
257     };
258     
259     /* Various color utility functions */
260     fb.pack = function (rgb) {
261          var r = Math.round(rgb[0] * 255);
262          var g = Math.round(rgb[1] * 255);
263          var b = Math.round(rgb[2] * 255);
264          return '#' + (r < 16 ? '0' : '') + r.toString(16) +
265               (g < 16 ? '0' : '') + g.toString(16) +
266               (b < 16 ? '0' : '') + b.toString(16);
267     };
268     
269     fb.unpack = function (color) {
270          if (color.length == 7) {
271               return [parseInt('0x' + color.substring(1, 3)) / 255,
272                    parseInt('0x' + color.substring(3, 5)) / 255,
273                    parseInt('0x' + color.substring(5, 7)) / 255];
274          }
275          else if (color.length == 4) {
276               return [parseInt('0x' + color.substring(1, 2)) / 15,
277                    parseInt('0x' + color.substring(2, 3)) / 15,
278                    parseInt('0x' + color.substring(3, 4)) / 15];
279          }
280     };
281     
282     fb.HSLToRGB = function (hsl) {
283          var m1, m2, r, g, b;
284          var h = hsl[0], s = hsl[1], l = hsl[2];
285          m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
286          m1 = l * 2 - m2;
287          return [this.hueToRGB(m1, m2, h+0.33333),
288               this.hueToRGB(m1, m2, h),
289               this.hueToRGB(m1, m2, h-0.33333)];
290     };
291     
292     fb.hueToRGB = function (m1, m2, h) {
293          h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
294          if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
295          if (h * 2 < 1) return m2;
296          if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
297          return m1;
298     };
299     
300     fb.RGBToHSL = function (rgb) {
301          var min, max, delta, h, s, l;
302          var r = rgb[0], g = rgb[1], b = rgb[2];
303          min = Math.min(r, Math.min(g, b));
304          max = Math.max(r, Math.max(g, b));
305          delta = max - min;
306          l = (min + max) / 2;
307          s = 0;
308          if (l > 0 && l < 1) {
309               s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
310          }
311          h = 0;
312          if (delta > 0) {
313               if (max == r && max != g) h += (g - b) / delta;
314               if (max == g && max != b) h += (2 + (b - r) / delta);
315               if (max == b && max != r) h += (4 + (r - g) / delta);
316               h /= 6;
317          }
318          return [h, s, l];
319     };
320     
321     // Install mousedown handler (the others are set on the document on-demand)
322     $('*', e).mousedown(fb.mousedown);
323     
324     // Init color
325     fb.setColor('#000000');
326     
327     // Set linked elements/callback
328     if (callback) {
329          fb.linkTo(callback);
330     }
331};
Note: See TracBrowser for help on using the repository browser.

Sites map