(function(root, factory) {
  if(typeof define === 'function' && define.amd)
    define(['./color', './drag'], factory);
  else root.colorjoe = factory(root.color, root.drag);
}(this, function(color, drag) {
var ret = function(element, initialColor) {
  var picker = element;
  if(isString(element)) picker = document.getElementById(element);

  if(picker) return setup(picker, initialColor);

  function setup(picker, col) {
    var hsv = color.hsva(col);

    picker.className = 'colorPicker';

    var div = partial(e, 'div');
    var twod = div('twod', picker);
    var p1 = div('pointer', twod);
    div('shape shape1', p1);
    div('shape shape2', p1);
    div('bg bg1', twod);
    div('bg bg2', twod);

    var oned = div('oned', picker);
    var p2 = div('pointer', oned);
    div('shape', p2);
    div('bg', oned);

    drag(oned, {
      begin: changeHS,
      change: changeHS,
      end: done
    });

    function changeHS(p) {
      hsv.h(p.y);
      H(p.y);
      changed(hsv);
    }

    drag(twod, {
      begin: changeS,
      change: changeS,
      end: done
    });

    function changeS(p) {
      hsv.s(p.x);
      hsv.v(1 - p.y);
      SV(p.x, p.y);
      changed(hsv);
    }

    H(hsv.h());
    SV(hsv.s(), 1 - hsv.v());

    function H(h) {
      p2.style.top = clamp(h * 100, 0, 100) + '%';
      twod.style.background = color.hsva({h: h, s: 1, v: 1}).toCSS();    
    }

    function SV(s, v) {
      p1.style.left = clamp(s * 100, 0, 100) + '%';
      p1.style.top = clamp(v * 100, 0, 100) + '%'; 
    }

    var changeListeners = [];
    function changed() {
      for(var i = 0, len = changeListeners.length; i < len; i++)
        changeListeners[i](hsv);
    }

    var doneListeners = [];
    function done() {
      for(var i = 0, len = doneListeners.length; i < len; i++)
        doneListeners[i](hsv);
    }

    var ob = {
      e: picker,
      update: function() {
        changed(hsv);

        return ob;
      },
      get: function() {
          return color.rgba(hsv);
      },
      set: function(c) {
        hsv = c;
        H(c.h());
        SV(c.s(), c.v());

        return ob;
      },
      on: function(evt, cb) {
        if(evt == 'change') changeListeners.push(cb);
        if(evt == 'done') doneListeners.push(cb);

        return ob;
      }
    };

    return ob;
  }
};

// helpers needed by rgbjoe
ret.partial = partial;
ret.e = e;

return ret;

function clamp(a, minValue, maxValue) {
  return Math.min(Math.max(a, minValue), maxValue);
}

function isString(o) {
  return typeof(o) === 'string';
}

function e(type, klass, p) {
  var elem = document.createElement(type);
  elem.className = klass;
  p.appendChild(elem);

  return elem;
}

// http://stackoverflow.com/questions/4394747/javascript-curry-function
function partial(fn) {
  var slice = Array.prototype.slice;
  var args = slice.apply(arguments, [1]);

  return function() {
    return fn.apply(null, args.concat(slice.apply(arguments)));
  };
}
}));

@@ -846,33 +846,32 @@
   begin: changeH
-S
 ,%0A      change: 
@@ -877,17 +877,16 @@
  changeH
-S
 ,%0A      
@@ -924,17 +924,16 @@
  changeH
-S
 (p) %7B%0A  
@@ -1018,32 +1018,33 @@
   begin: changeS
+V
 ,%0A      change: 
@@ -1050,16 +1050,17 @@
  changeS
+V
 ,%0A      
@@ -1098,16 +1098,17 @@
  changeS
+V
 (p) %7B%0A  

Tidy up