source: extensions/charlies_content/farbtastic/farbtastic.js @ 31482

Last change on this file since 31482 was 3318, checked in by vdigital, 16 years ago

+ Add Charlies' content to depository

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1// $Id: farbtastic.js 3318 2009-05-20 21:54:10Z vdigital $
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  fb.updateValue = function (event) {
67    if (this.value && this.value != fb.color) {
68      fb.setColor(this.value);
69    }
70  }
71
72  /**
73   * Change color with HTML syntax #123456
74   */
75  fb.setColor = function (color) {
76    var unpack = fb.unpack(color);
77    if (fb.color != color && unpack) {
78      fb.color = color;
79      fb.rgb = unpack;
80      fb.hsl = fb.RGBToHSL(fb.rgb);
81      fb.updateDisplay();
82    }
83    return this;
84  }
85
86  /**
87   * Change color with HSL triplet [0..1, 0..1, 0..1]
88   */
89  fb.setHSL = function (hsl) {
90    fb.hsl = hsl;
91    fb.rgb = fb.HSLToRGB(hsl);
92    fb.color = fb.pack(fb.rgb);
93    fb.updateDisplay();
94    return this;
95  }
96
97  /////////////////////////////////////////////////////
98
99  /**
100   * Retrieve the coordinates of the given event relative to the center
101   * of the widget.
102   */
103  fb.widgetCoords = function (event) {
104    var x, y;
105    var el = event.target || event.srcElement;
106    var reference = fb.wheel;
107
108    if (typeof event.offsetX != 'undefined') {
109      // Use offset coordinates and find common offsetParent
110      var pos = { x: event.offsetX, y: event.offsetY };
111
112      // Send the coordinates upwards through the offsetParent chain.
113      var e = el;
114      while (e) {
115        e.mouseX = pos.x;
116        e.mouseY = pos.y;
117        pos.x += e.offsetLeft;
118        pos.y += e.offsetTop;
119        e = e.offsetParent;
120      }
121
122      // Look for the coordinates starting from the wheel widget.
123      var e = reference;
124      var offset = { x: 0, y: 0 }
125      while (e) {
126        if (typeof e.mouseX != 'undefined') {
127          x = e.mouseX - offset.x;
128          y = e.mouseY - offset.y;
129          break;
130        }
131        offset.x += e.offsetLeft;
132        offset.y += e.offsetTop;
133        e = e.offsetParent;
134      }
135
136      // Reset stored coordinates
137      e = el;
138      while (e) {
139        e.mouseX = undefined;
140        e.mouseY = undefined;
141        e = e.offsetParent;
142      }
143    }
144    else {
145      // Use absolute coordinates
146      var pos = fb.absolutePosition(reference);
147      x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
148      y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
149    }
150    // Subtract distance to middle
151    return { x: x - fb.width / 2, y: y - fb.width / 2 };
152  }
153
154  /**
155   * Mousedown handler
156   */
157  fb.mousedown = function (event) {
158    // Capture mouse
159    if (!document.dragging) {
160      $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
161      document.dragging = true;
162    }
163
164    // Check which area is being dragged
165    var pos = fb.widgetCoords(event);
166    fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
167
168    // Process
169    fb.mousemove(event);
170    return false;
171  }
172
173  /**
174   * Mousemove handler
175   */
176  fb.mousemove = function (event) {
177    // Get coordinates relative to color picker center
178    var pos = fb.widgetCoords(event);
179
180    // Set new HSL parameters
181    if (fb.circleDrag) {
182      var hue = Math.atan2(pos.x, -pos.y) / 6.28;
183      if (hue < 0) hue += 1;
184      fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
185    }
186    else {
187      var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
188      var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
189      fb.setHSL([fb.hsl[0], sat, lum]);
190    }
191    return false;
192  }
193
194  /**
195   * Mouseup handler
196   */
197  fb.mouseup = function () {
198    // Uncapture mouse
199    $(document).unbind('mousemove', fb.mousemove);
200    $(document).unbind('mouseup', fb.mouseup);
201    document.dragging = false;
202  }
203
204  /**
205   * Update the markers and styles
206   */
207  fb.updateDisplay = function () {
208    // Markers
209    var angle = fb.hsl[0] * 6.28;
210    $('.h-marker', e).css({
211      left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
212      top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
213    });
214
215    $('.sl-marker', e).css({
216      left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
217      top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
218    });
219
220    // Saturation/Luminance gradient
221    $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
222
223    // Linked elements or callback
224    if (typeof fb.callback == 'object') {
225      // Set background/foreground color
226      $(fb.callback).css({
227        backgroundColor: fb.color,
228        color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
229      });
230
231      // Change linked value
232      $(fb.callback).each(function() {
233        if (this.value && this.value != fb.color) {
234          this.value = fb.color;
235        }
236      });
237    }
238    else if (typeof fb.callback == 'function') {
239      fb.callback.call(fb, fb.color);
240    }
241  }
242
243  /**
244   * Get absolute position of element
245   */
246  fb.absolutePosition = function (el) {
247    var r = { x: el.offsetLeft, y: el.offsetTop };
248    // Resolve relative to offsetParent
249    if (el.offsetParent) {
250      var tmp = fb.absolutePosition(el.offsetParent);
251      r.x += tmp.x;
252      r.y += tmp.y;
253    }
254    return r;
255  };
256
257  /* Various color utility functions */
258  fb.pack = function (rgb) {
259    var r = Math.round(rgb[0] * 255);
260    var g = Math.round(rgb[1] * 255);
261    var b = Math.round(rgb[2] * 255);
262    return '#' + (r < 16 ? '0' : '') + r.toString(16) +
263           (g < 16 ? '0' : '') + g.toString(16) +
264           (b < 16 ? '0' : '') + b.toString(16);
265  }
266
267  fb.unpack = function (color) {
268    if (color.length == 7) {
269      return [parseInt('0x' + color.substring(1, 3)) / 255,
270        parseInt('0x' + color.substring(3, 5)) / 255,
271        parseInt('0x' + color.substring(5, 7)) / 255];
272    }
273    else if (color.length == 4) {
274      return [parseInt('0x' + color.substring(1, 2)) / 15,
275        parseInt('0x' + color.substring(2, 3)) / 15,
276        parseInt('0x' + color.substring(3, 4)) / 15];
277    }
278  }
279
280  fb.HSLToRGB = function (hsl) {
281    var m1, m2, r, g, b;
282    var h = hsl[0], s = hsl[1], l = hsl[2];
283    m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
284    m1 = l * 2 - m2;
285    return [this.hueToRGB(m1, m2, h+0.33333),
286        this.hueToRGB(m1, m2, h),
287        this.hueToRGB(m1, m2, h-0.33333)];
288  }
289
290  fb.hueToRGB = function (m1, m2, h) {
291    h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
292    if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
293    if (h * 2 < 1) return m2;
294    if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
295    return m1;
296  }
297
298  fb.RGBToHSL = function (rgb) {
299    var min, max, delta, h, s, l;
300    var r = rgb[0], g = rgb[1], b = rgb[2];
301    min = Math.min(r, Math.min(g, b));
302    max = Math.max(r, Math.max(g, b));
303    delta = max - min;
304    l = (min + max) / 2;
305    s = 0;
306    if (l > 0 && l < 1) {
307      s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
308    }
309    h = 0;
310    if (delta > 0) {
311      if (max == r && max != g) h += (g - b) / delta;
312      if (max == g && max != b) h += (2 + (b - r) / delta);
313      if (max == b && max != r) h += (4 + (r - g) / delta);
314      h /= 6;
315    }
316    return [h, s, l];
317  }
318
319  // Install mousedown handler (the others are set on the document on-demand)
320  $('*', e).mousedown(fb.mousedown);
321
322    // Init color
323  fb.setColor('#000000');
324
325  // Set linked elements/callback
326  if (callback) {
327    fb.linkTo(callback);
328  }
329}
Note: See TracBrowser for help on using the repository browser.