topical media & game development

talk show tell print

mobile-query-three-plugins-assets-vendor-dat.gui-dat.color.js / js



  
dat-gui JavaScript Controller Library http://code.google.com/p/dat-gui Copyright 2011 Data Arts Team, Google Creative Lab Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

  
  
  
@namespace

  
  var dat = dat || {};
  
  
@namespace

  
  dat.color = dat.color || {};
  
  
@namespace

  
  dat.utils = dat.utils || {};
  
  dat.utils.common = (function () {
    
    var ARR_EACH = Array.prototype.forEach;
    var ARR_SLICE = Array.prototype.slice;
  
    
Band-aid methods for things that should be a lot easier in JavaScript. Implementation and structure inspired by underscore.js http://documentcloud.github.com/underscore/

  
  
    return { 
      
      BREAK: {},
    
      extend: function(target) {
        
        this.each(ARR_SLICE.call(arguments, 1), function(obj) {
          
          for (var key in obj)
            if (!this.isUndefined(obj[key])) 
              target[key] = obj[key];
          
        }, this);
        
        return target;
        
      },
      
      defaults: function(target) {
        
        this.each(ARR_SLICE.call(arguments, 1), function(obj) {
          
          for (var key in obj)
            if (this.isUndefined(target[key])) 
              target[key] = obj[key];
          
        }, this);
        
        return target;
      
      },
      
      compose: function() {
        var toCall = ARR_SLICE.call(arguments);
              return function() {
                var args = ARR_SLICE.call(arguments);
                for (var i = toCall.length -1; i >= 0; i--) {
                  args = [toCall[i].apply(this, args)];
                }
                return args[0];
              }
      },
      
      each: function(obj, itr, scope) {
  
        
        if (ARR_EACH && obj.forEach === ARR_EACH) { 
          
          obj.forEach(itr, scope);
          
        } else if (obj.length === obj.length + 0) { // Is number but not NaN
          
          for (var key = 0, l = obj.length; key < l; key++)
            if (key in obj && itr.call(scope, obj[key], key) === this.BREAK) 
              return;
              
        } else {
  
          for (var key in obj) 
            if (itr.call(scope, obj[key], key) === this.BREAK)
              return;
              
        }
              
      },
      
      defer: function(fnc) {
        setTimeout(fnc, 0);
      },
      
      toArray: function(obj) {
        if (obj.toArray) return obj.toArray();
        return ARR_SLICE.call(obj);
      },
  
      isUndefined: function(obj) {
        return obj === undefined;
      },
      
      isNull: function(obj) {
        return obj === null;
      },
      
      isNaN: function(obj) {
        return obj !== obj;
      },
      
      isArray: Array.isArray || function(obj) {
        return obj.constructor === Array;
      },
      
      isObject: function(obj) {
        return obj === Object(obj);
      },
      
      isNumber: function(obj) {
        return obj === obj+0;
      },
      
      isString: function(obj) {
        return obj === obj+'';
      },
      
      isBoolean: function(obj) {
        return obj === false || obj === true;
      },
      
      isFunction: function(obj) {
        return Object.prototype.toString.call(obj) === '[object Function]';
      }
    
    };
      
  })();
  
  dat.color.toString = (function (common) {
  
    return function(color) {
  
      if (color.a == 1 || common.isUndefined(color.a)) {
  
        var s = color.hex.toString(16);
        while (s.length < 6) {
          s = '0' + s;
        }
  
        return '#' + s;
  
      } else {
  
        return 'rgba(' + Math.round(color.r) + ',' + Math.round(color.g) + ',' + Math.round(color.b) + ',' + color.a + ')';
  
      }
  
    }
  
  })(dat.utils.common);
  
  dat.Color = dat.color.Color = (function (interpret, math, toString, common) {
  
    var Color = function() {
  
      this.__state = interpret.apply(this, arguments);
  
      if (this.__state === false) {
        throw 'Failed to interpret color arguments';
      }
  
      this.__state.a = this.__state.a || 1;
  
    };
  
    Color.COMPONENTS = ['r','g','b','h','s','v','hex','a'];
  
    common.extend(Color.prototype, {
  
      toString: function() {
        return toString(this);
      },
  
      toOriginal: function() {
        return this.__state.conversion.write(this);
      }
  
    });
  
    defineRGBComponent(Color.prototype, 'r', 2);
    defineRGBComponent(Color.prototype, 'g', 1);
    defineRGBComponent(Color.prototype, 'b', 0);
  
    defineHSVComponent(Color.prototype, 'h');
    defineHSVComponent(Color.prototype, 's');
    defineHSVComponent(Color.prototype, 'v');
  
    Object.defineProperty(Color.prototype, 'a', {
  
      get: function() {
        return this.__state.a;
      },
  
      set: function(v) {
        this.__state.a = v;
      }
  
    });
  
    Object.defineProperty(Color.prototype, 'hex', {
  
      get: function() {
  
        if (!this.__state.space !== 'HEX') {
          this.__state.hex = math.rgb_to_hex(this.r, this.g, this.b);
        }
  
        return this.__state.hex;
  
      },
  
      set: function(v) {
  
        this.__state.space = 'HEX';
        this.__state.hex = v;
  
      }
  
    });
  
    function defineRGBComponent(target, component, componentHexIndex) {
  
      Object.defineProperty(target, component, {
  
        get: function() {
  
          if (this.__state.space === 'RGB') {
            return this.__state[component];
          }
  
          recalculateRGB(this, component, componentHexIndex);
  
          return this.__state[component];
  
        },
  
        set: function(v) {
  
          if (this.__state.space !== 'RGB') {
            recalculateRGB(this, component, componentHexIndex);
            this.__state.space = 'RGB';
          }
  
          this.__state[component] = v;
  
        }
  
      });
  
    }
  
    function defineHSVComponent(target, component) {
  
      Object.defineProperty(target, component, {
  
        get: function() {
  
          if (this.__state.space === 'HSV')
            return this.__state[component];
  
          recalculateHSV(this);
  
          return this.__state[component];
  
        },
  
        set: function(v) {
  
          if (this.__state.space !== 'HSV') {
            recalculateHSV(this);
            this.__state.space = 'HSV';
          }
  
          this.__state[component] = v;
  
        }
  
      });
  
    }
  
    function recalculateRGB(color, component, componentHexIndex) {
  
      if (color.__state.space === 'HEX') {
  
        color.__state[component] = math.component_from_hex(color.__state.hex, componentHexIndex);
  
      } else if (color.__state.space === 'HSV') {
  
        common.extend(color.__state, math.hsv_to_rgb(color.__state.h, color.__state.s, color.__state.v));
  
      } else {
  
        throw 'Corrupted color state';
  
      }
  
    }
  
    function recalculateHSV(color) {
  
      var result = math.rgb_to_hsv(color.r, color.g, color.b);
  
      common.extend(color.__state,
          {
            s: result.s,
            v: result.v
          }
      );
  
      if (!common.isNaN(result.h)) {
        color.__state.h = result.h;
      } else if (common.isUndefined(color.__state.h)) {
        color.__state.h = 0;
      }
  
    }
  
    return Color;
  
  })(dat.color.interpret = (function (toString, common) {
  
    var result, toReturn;
  
    var interpret = function() {
  
      toReturn = false;
  
      var original = arguments.length > 1 ? common.toArray(arguments) : arguments[0];
  
      common.each(INTERPRETATIONS, function(family) {
  
        if (family.litmus(original)) {
  
          common.each(family.conversions, function(conversion, conversionName) {
  
            result = conversion.read(original);
  
            if (toReturn === false && result !== false) {
              toReturn = result;
              result.conversionName = conversionName;
              result.conversion = conversion;
              return common.BREAK;
  
            }
  
          });
  
          return common.BREAK;
  
        }
  
      });
  
      return toReturn;
  
    };
  
    var INTERPRETATIONS = [
  
      // Strings
      {
  
        litmus: common.isString,
  
        conversions: {
  
          THREE_CHAR_HEX: {
  
            read: function(original) {
  
              var test = original.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])/i);
              if (test === null) return false;
  
              return {
                space: 'HEX',
                hex: parseInt(
                    '0x' +
                        test[1].toString() + test[1].toString() +
                        test[2].toString() + test[2].toString() +
                        test[3].toString() + test[3].toString())
              };
  
            },
  
            write: toString
  
          },
  
          SIX_CHAR_HEX: {
  
            read: function(original) {
  
              var test = original.match(/^#([A-F0-9]{6})/i);
              if (test === null) return false;
  
              return {
                space: 'HEX',
                hex: parseInt('0x' + test[1].toString())
              };
  
            },
  
            write: toString
  
          },
  
          CSS_RGB: {
  
            read: function(original) {
  
              var test = original.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
              if (test === null) return false;
  
              return {
                space: 'RGB',
                r: parseFloat(test[1]),
                g: parseFloat(test[2]),
                b: parseFloat(test[3])
              };
  
            },
  
            write: toString
  
          },
  
          CSS_RGBA: {
  
            read: function(original) {
  
              var test = original.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s* \s*(.+)\s*\)/);
              if (test === null) return false;
  
              return {
                space: 'RGB',
                r: parseFloat(test[1]),
                g: parseFloat(test[2]),
                b: parseFloat(test[3]),
                a: parseFloat(test[4])
              };
  
            },
  
            write: toString
  
          }
  
        }
  
      },
  
      // Numbers
      {
  
        litmus: common.isNumber,
  
        conversions: {
  
          HEX: {
            read: function(original) {
              return {
                space: 'HEX',
                hex: original,
                conversionName: 'HEX'
              }
            },
  
            write: function(color) {
              return color.hex;
            }
          }
  
        }
  
      },
  
      // Arrays
      {
  
        litmus: common.isArray,
  
        conversions: {
  
          RGB_ARRAY: {
            read: function(original) {
              if (original.length != 3) return false;
              return {
                space: 'RGB',
                r: original[0],
                g: original[1],
                b: original[2]
              };
            },
  
            write: function(color) {
              return [color.r, color.g, color.b];
            }
  
          },
  
          RGBA_ARRAY: {
            read: function(original) {
              if (original.length != 4) return false;
              return {
                space: 'RGB',
                r: original[0],
                g: original[1],
                b: original[2],
                a: original[3]
              };
            },
  
            write: function(color) {
              return [color.r, color.g, color.b, color.a];
            }
  
          }
  
        }
  
      },
  
      // Objects
      {
  
        litmus: common.isObject,
  
        conversions: {
  
          RGBA_OBJ: {
            read: function(original) {
              if (common.isNumber(original.r) &&
                  common.isNumber(original.g) &&
                  common.isNumber(original.b) &&
                  common.isNumber(original.a)) {
                return {
                  space: 'RGB',
                  r: original.r,
                  g: original.g,
                  b: original.b,
                  a: original.a
                }
              }
              return false;
            },
  
            write: function(color) {
              return {
                r: color.r,
                g: color.g,
                b: color.b,
                a: color.a
              }
            }
          },
  
          RGB_OBJ: {
            read: function(original) {
              if (common.isNumber(original.r) &&
                  common.isNumber(original.g) &&
                  common.isNumber(original.b)) {
                return {
                  space: 'RGB',
                  r: original.r,
                  g: original.g,
                  b: original.b
                }
              }
              return false;
            },
  
            write: function(color) {
              return {
                r: color.r,
                g: color.g,
                b: color.b
              }
            }
          },
  
          HSVA_OBJ: {
            read: function(original) {
              if (common.isNumber(original.h) &&
                  common.isNumber(original.s) &&
                  common.isNumber(original.v) &&
                  common.isNumber(original.a)) {
                return {
                  space: 'HSV',
                  h: original.h,
                  s: original.s,
                  v: original.v,
                  a: original.a
                }
              }
              return false;
            },
  
            write: function(color) {
              return {
                h: color.h,
                s: color.s,
                v: color.v,
                a: color.a
              }
            }
          },
  
          HSV_OBJ: {
            read: function(original) {
              if (common.isNumber(original.h) &&
                  common.isNumber(original.s) &&
                  common.isNumber(original.v)) {
                return {
                  space: 'HSV',
                  h: original.h,
                  s: original.s,
                  v: original.v
                }
              }
              return false;
            },
  
            write: function(color) {
              return {
                h: color.h,
                s: color.s,
                v: color.v
              }
            }
  
          }
  
        }
  
      }
  
    ];
  
    return interpret;
  
  })(dat.color.toString,
  dat.utils.common),
  dat.color.math = (function () {
  
    var tmpComponent;
  
    return {
  
      hsv_to_rgb: function(h, s, v) {
  
        var hi = Math.floor(h / 60) % 6;
  
        var f = h / 60 - Math.floor(h / 60);
        var p = v * (1.0 - s);
        var q = v * (1.0 - (f * s));
        var t = v * (1.0 - ((1.0 - f) * s));
        var c = [
          [v, t, p],
          [q, v, p],
          [p, v, t],
          [p, q, v],
          [t, p, v],
          [v, p, q]
        ][hi];
  
        return {
          r: c[0] * 255,
          g: c[1] * 255,
          b: c[2] * 255
        };
  
      },
  
      rgb_to_hsv: function(r, g, b) {
  
        var min = Math.min(r, g, b),
            max = Math.max(r, g, b),
            delta = max - min,
            h, s;
  
        if (max != 0) {
          s = delta / max;
        } else {
          return {
            h: NaN,
            s: 0,
            v: 0
          };
        }
  
        if (r == max) {
          h = (g - b) / delta;
        } else if (g == max) {
          h = 2 + (b - r) / delta;
        } else {
          h = 4 + (r - g) / delta;
        }
        h /= 6;
        if (h < 0) {
          h += 1;
        }
  
        return {
          h: h * 360,
          s: s,
          v: max / 255
        };
      },
  
      rgb_to_hex: function(r, g, b) {
        var hex = this.hex_with_component(0, 2, r);
        hex = this.hex_with_component(hex, 1, g);
        hex = this.hex_with_component(hex, 0, b);
        return hex;
      },
  
      component_from_hex: function(hex, componentIndex) {
        return (hex >> (componentIndex * 8)) & 0xFF;
      },
  
      hex_with_component: function(hex, componentIndex, value) {
        return value << (tmpComponent = componentIndex * 8) | (hex & ~ (0xFF << tmpComponent));
      }
  
    }
  
  })(),
  dat.color.toString,
  dat.utils.common);


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.