text: ;(function($, Colors, undefined){
  	'use strict';
  
  	var $document = $(document),
  		_instance,
  		_colorPicker,
  		_color,
  		_options,
  		_selector = '',
  
  		_$trigger,
  		_$UI, _$xy_slider, _$xy_cursor, _$z_cursor , _$alpha , _$alpha_cursor,
  
  		_pointermove = 'touchmove mousemove pointermove',
  		_pointerup = 'touchend mouseup pointerup',
  		_GPU = false,
  		_animate = window.requestAnimationFrame ||
  			window.webkitRequestAnimationFrame || function(cb){cb()},
  		_html = '<div class="cp-color-picker"><div class="cp-z-slider"><div c' +
  			'lass="cp-z-cursor"></div></div><div class="cp-xy-slider"><div cl' +
  			'ass="cp-white"></div><div class="cp-xy-cursor"></div></div><div ' +
  			'class="cp-alpha"><div class="cp-alpha-cursor"></div></div></div>',
  			// 'grunt-contrib-uglify' puts all this back to one single string...
  		_css = '.cp-color-picker{position:absolute;overflow:hidden;padding:6p' +
  			'x 6px 0;background-color:#444;color:#bbb;font-family:Arial,Helve' +
  			'tica,sans-serif;font-size:12px;font-weight:400;cursor:default;bo' +
  			'rder-radius:5px}.cp-color-picker>div{position:relative;overflow:' +
  			'hidden}.cp-xy-slider{float:left;height:128px;width:128px;margin-' +
  			'bottom:6px;background:linear-gradient(to right,#FFF,rgba(255,255' +
  			',255,0))}.cp-white{height:100%;width:100%;background:linear-grad' +
  			'ient(rgba(0,0,0,0),#000)}.cp-xy-cursor{position:absolute;top:0;w' +
  			'idth:10px;height:10px;margin:-5px;border:1px solid #fff;border-r' +
  			'adius:100%;box-sizing:border-box}.cp-z-slider{float:right;margin' +
  			'-left:6px;height:128px;width:20px;background:linear-gradient(red' +
  			' 0,#f0f 17%,#00f 33%,#0ff 50%,#0f0 67%,#ff0 83%,red 100%)}.cp-z-' +
  			'cursor{position:absolute;margin-top:-4px;width:100%;border:4px s' +
  			'olid #fff;border-color:transparent #fff;box-sizing:border-box}.c' +
  			'p-alpha{clear:both;width:100%;height:16px;margin:6px 0;backgroun' +
  			'd:linear-gradient(to right,#444,rgba(0,0,0,0))}.cp-alpha-cursor{' +
  			'position:absolute;margin-left:-4px;height:100%;border:4px solid ' +
  			'#fff;border-color:#fff transparent;box-sizing:border-box}',
  
  		ColorPicker = function(options) {
  			_color = this.color = new Colors(options);
  			_options = _color.options;
  		};
  
  	ColorPicker.prototype = {
  		render: preRender,
  		toggle: toggle
  	}
  
  	function extractValue(elm) {
  		return elm.value || elm.getAttribute('value') ||
  			$(elm).css('background-color') || '#fff';
  	}
  
  	function resolveEventType(event) {
  		return event.originalEvent.touches ?
  			event.originalEvent.touches[0] : event;
  	}
  
  	function findElement($elm) {
  		return $($elm.find(_options.doRender)[0] || $elm[0]);
  	}
  
  	function toggle(event) {
  		var $this = $(this),
  			position = $this.offset(),
  			$window = $(window),
  			gap = _options.gap;
  
  		if (event) {
  			_$trigger = findElement($this);
  			_colorPicker.$trigger = $this;
  
  			(_$UI || build()).css({
  				// 'width': _$UI[0]._width,
  				'left': (_$UI[0]._left = position.left) -
  					((_$UI[0]._left = _$UI[0]._left + _$UI[0]._width -
  					($window.scrollLeft() + $window.width())) + gap > 0 ?
  					_$UI[0]._left + gap : 0),
  				'top': (_$UI[0]._top = position.top + $this.outerHeight()) -
  					((_$UI[0]._top = _$UI[0]._top + _$UI[0]._height -
  					($window.scrollTop() + $window.height())) + gap > 0 ?
  					_$UI[0]._top + gap : 0)
  			}).show(_options.animationSpeed, function() {
  				if (event === true) {
  					return;
  				}
  				_$alpha._width = _$alpha.width();
  				_$xy_slider._width = _$xy_slider.width();
  				_$xy_slider._height = _$xy_slider.height();
  				_color.setColor(extractValue(_$trigger[0]));
  
  				preRender(true);
  			});
  		} else {
  			if ($(_$UI).is(":visible")) {
  				$(_$UI).hide(_options.animationSpeed, function() {
  					_$trigger.blur();
  					_colorPicker.$trigger = null;
  					preRender(false);
  				});
  			}
  		}
  	};
  
  	function build() {
  		$('head').append('<style type="text/css">' +
  			(_options.css || _css) + (_options.cssAddon || '') + '</style>');
  
  		return _colorPicker.$UI = _$UI =
  			$(_html).css({'margin': _options.margin}).
  			appendTo('body').
  			show(0, function() {
  				var $this = $(this);
  
  				_GPU = _options.GPU && $this.css('perspective') !== undefined;
  				_$xy_slider = $('.cp-xy-slider', this);
  				_$xy_cursor = $('.cp-xy-cursor', this);
  				_$z_cursor = $('.cp-z-cursor', this);
  				_$alpha = $('.cp-alpha', this).toggle(!!_options.opacity);
  				_$alpha_cursor = $('.cp-alpha-cursor', this);
  				_options.buildCallback.call(_colorPicker, $this);
  				$this.prepend('<div>').children().eq(0).css('width',
  					$this.children().eq(0).width() // stabilizer
  				);
  				this._width = this.offsetWidth;
  				this._height = this.offsetHeight;
  			}).hide().
  			on('touchstart mousedown pointerdown',
  				'.cp-xy-slider,.cp-z-slider,.cp-alpha', pointerdown);
  	}
  
  	function pointerdown(e) {
  		var action = this.className.
  				replace(/cp-(.*?)(?:\s*|$)/, '$1').replace('-', '_');
  
  		e.preventDefault && e.preventDefault();
  		e.returnValue = false;
  
  		_$trigger._offset = $(this).offset();
  		(action = action === 'xy_slider' ? xy_slider :
  			action === 'z_slider' ? z_slider : alpha)(e);
  
  		$document.on(_pointerup, pointerup).on(_pointermove, action);
  	}
  
  	function pointerup(e) {
  		$document.off(_pointermove).off(_pointerup);
  	}
  
  	function xy_slider(event) {
  		var e = resolveEventType(event),
  			x = e.pageX - _$trigger._offset.left,
  			y = e.pageY - _$trigger._offset.top;
  
  		_color.setColor({
  			s: x / _$xy_slider._width * 100,
  			v: 100 - (y / _$xy_slider._height * 100)
  		}, 'hsv');
  		preRender();
  	}
  
  	function z_slider(event) {
  		var z = resolveEventType(event).pageY - _$trigger._offset.top,
  			hsv = _color.colors.hsv;
  
  		_color.setColor({h: 360 - (z / _$xy_slider._height * 360)}, 'hsv');
  		preRender();
  	}
  
  	function alpha(event) {
  		var x = resolveEventType(event).pageX - _$trigger._offset.left,
  			alpha = x / _$alpha._width;
  
  		_color.setColor({}, 'rgb', alpha > 1 ? 1 : alpha < 0 ? 0 : alpha);
  		preRender();
  	}
  
  	function preRender(toggled) {
  		var colors = _color.colors,
  			hueRGB = colors.hueRGB,
  			RGB = colors.RND.rgb,
  			HSL = colors.RND.hsl,
  			dark = '#222',
  			light = '#ddd',
  			colorMode = _$trigger.data('colorMode'),
  			isAlpha = colors.alpha !== 1,
  			alpha = Math.round(colors.alpha * 100) / 100,
  			RGBInnerText = RGB.r + ', ' + RGB.g + ', ' + RGB.b,
  			text = (colorMode === 'HEX' && !isAlpha ? '#' + colors.HEX :
  				colorMode === 'rgb' || (colorMode === 'HEX' && isAlpha) ?
  				(!isAlpha ? 'rgb(' + RGBInnerText + ')' :
  					'rgba(' + RGBInnerText + ', ' + alpha + ')') :
  				('hsl' + (isAlpha ? 'a(' : '(') + HSL.h + ', ' + HSL.s + '%, ' +
  					HSL.l + '%' + (isAlpha ? ', ' + alpha : '') + ')')),
  			HUEContrast = colors.HUELuminance > 0.22 ? dark : light,
  			alphaContrast = colors.rgbaMixBlack.luminance > 0.22 ? dark : light,
  			h = (1 - colors.hsv.h) * _$xy_slider._height,
  			s = colors.hsv.s * _$xy_slider._width,
  			v = (1 - colors.hsv.v) * _$xy_slider._height,
  			a = alpha * _$alpha._width,
  			translate3d = _GPU ? 'translate3d' : '',
  			triggerValue = _$trigger.val(),
  			hasNoValue = _$trigger[0].hasAttribute('value') &&
  				triggerValue === '' && toggled !== undefined;
  
  		_$xy_slider._css = {
  			backgroundColor: 'rgb(' +
  				hueRGB.r + ',' + hueRGB.g + ',' + hueRGB.b + ')'};
  		_$xy_cursor._css = {
  			transform: translate3d + '(' + s + 'px, ' + v + 'px, 0)',
  			left: !_GPU ? s : '',
  			top: !_GPU ? v : '',
  			borderColor : colors.RGBLuminance > 0.22 ? dark : light
  		};
  		_$z_cursor._css = {
  			transform: translate3d + '(0, ' + h + 'px, 0)',
  			top: !_GPU ? h : '',
  			borderColor : 'transparent ' + HUEContrast
  		};
  		_$alpha._css = {backgroundColor: 'rgb(' + RGBInnerText + ')'};
  		_$alpha_cursor._css = {
  			transform: translate3d + '(' + a + 'px, 0, 0)',
  			left: !_GPU ? a : '',
  			borderColor : alphaContrast + ' transparent'
  		};
  		_$trigger._css = {
  			backgroundColor : hasNoValue ? '' : text,
  			color: hasNoValue ? '' :
  				colors.rgbaMixBGMixCustom.luminance > 0.22 ? dark : light
  		};
  		_$trigger.text = hasNoValue ? '' : triggerValue !== text ? text : '';
  
  		toggled !== undefined ? render(toggled) : _animate(render);
  	}
  
  	// As _animate() is actually requestAnimationFrame(), render() gets called
  	// decoupled from any pointer action (whenever the browser decides to do
  	// so) as an event. preRender() is coupled to toggle() and all pointermove
  	// actions; that's where all the calculations happen. render() can now be
  	// called without extra calculations which results in faster rendering.
  	function render(toggled) {
  		_$xy_slider.css(_$xy_slider._css);
  		_$xy_cursor.css(_$xy_cursor._css);
  		_$z_cursor.css(_$z_cursor._css);
  		_$alpha.css(_$alpha._css);
  		_$alpha_cursor.css(_$alpha_cursor._css);
  
  		if (toggled!==false) {
  			_options.doRender && _$trigger.css(_$trigger._css);
  			_$trigger.text && _$trigger.val(_$trigger.text);
  		}
  
  		_options.renderCallback.call(
  			_colorPicker,
  			_$trigger,
  			typeof toggled === 'boolean' ? toggled : undefined
  		);
  	}
  
  	$.fn.colorPicker = function(options) {
  		var noop = function(){};
  
   		options = $.extend({
  			animationSpeed: 150,
  			GPU: true,
  			doRender: true,
  			customBG: '#FFF',
  			opacity: true,
  			renderCallback: noop,
  			buildCallback: noop,
  			body: document.body,
  			scrollResize: true,
  			gap: 4
  			// css: '',
  			// cssAddon: '',
  			// margin: '',
  			// preventFocus: false
  		}, options);
  
  		!_colorPicker && options.scrollResize && $(window).
  		on('resize scroll', function() {
  			if (_colorPicker.$trigger) {
  				_colorPicker.toggle.call(_colorPicker.$trigger[0], true);
  			}
  		});
  		_instance = _instance ? _instance.add(this) : this;
  		_instance.colorPicker = _colorPicker ||
  			(_colorPicker = new ColorPicker(options));
  		_selector += (_selector ? ', ' : '') + this.selector;
  
   		$(options.body).off('.a').
   		on('touchstart.a mousedown.a pointerdown.a', function(e) {
  			var $target = $(e.target);
  			if ($.inArray($target.closest(_selector)[0],
  				_instance) === -1 &&
  			!$target.closest(_$UI).length) {
  				toggle();
  			}
  		}).
  		on('focus.a click.a', _selector, toggle).
  		on('change.a', _selector, function(e) {
  			var val = this.value;
  			_color.setColor(val || '#FFF');
  			if (!val) {
  				toggle();
  				this.value = '';
  				$(e.target).css('backgroundColor', '#fff');
  			} else
  				_instance.colorPicker.render(true);
  		});
  
  		return this.each(function() {
  			var value = extractValue(this),
  				mode = value.split('('),
  				$elm = findElement($(this));
  
  			$elm.data('colorMode', mode[1] ? mode[0].substr(0, 3) : 'HEX').
  			attr('readonly', _options.preventFocus);
  			options.doRender && $elm.
  			css({'background-color': value,
  				'color': function() {
  					return _color.setColor(value).
  						rgbaMixBGMixCustom.luminance > 0.22 ? '#222' : '#ddd'
  				}
  			});
  		});
  	};
  })(jQuery, Colors);