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