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 }; |
