Mercurial > defr > drupal > core
comparison misc/farbtastic/farbtastic.js @ 1:c1f4ac30525a 6.0
Drupal 6.0
author | Franck Deroche <webmaster@defr.org> |
---|---|
date | Tue, 23 Dec 2008 14:28:28 +0100 |
parents | |
children | fff6d4c8c043 |
comparison
equal
deleted
inserted
replaced
0:5a113a1c4740 | 1:c1f4ac30525a |
---|---|
1 // $Id: farbtastic.js,v 1.4 2007/06/01 09:05:45 unconed Exp $ | |
2 // Farbtastic 1.2 | |
3 | |
4 jQuery.fn.farbtastic = function (callback) { | |
5 $.farbtastic(this, callback); | |
6 return this; | |
7 }; | |
8 | |
9 jQuery.farbtastic = function (container, callback) { | |
10 var container = $(container).get(0); | |
11 return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); | |
12 }; | |
13 | |
14 jQuery._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 }; |