;(function(factory) { if(typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if(typeof exports === 'object') { module.exports = factory(require("jquery")); } else { factory(jQuery); } } (function($) { var pluginName = "tinycolorpicker" , defaults = { colors : ["#ffffff", "#A7194B","#FE2712","#FB9902","#FABC02","#FEFE33","#D0EA2B","#66B032","#0391CE","#0247FE","#3D01A5","#8601AF"] , backgroundUrl : null } ; function Plugin($container, options) { /** * The options of the colorpicker extended with the defaults. * * @property options * @type Object */ this.options = $.extend({}, defaults, options); /** * @property _defaults * @type Object * @private * @default defaults */ this._defaults = defaults; /** * @property _name * @type String * @private * @final * @default 'tinycolorpicker' */ this._name = pluginName; var self = this , $track = $container.find(".track") , $color = $container.find(".color") , $canvas = null , $colorInput = $container.find(".colorInput") , $dropdown = $container.find(".dropdown") , $dropdownItem = $dropdown.find("li").remove() , context = null , mouseIsDown = false , hasCanvas = !!document.createElement("canvas").getContext , touchEvents = "ontouchstart" in document.documentElement ; /** * The current active color in hex. * * @property colorHex * @type String * @default "" */ this.colorHex = ""; /** * The current active color in rgb. * * @property colorRGB * @type String * @default "" */ this.colorRGB = ""; /** * @method _initialize * @private */ function _initialize() { if(hasCanvas) { $canvas = $(""); $track.append($canvas); context = $canvas[0].getContext( "2d" ); _setImage(); } else { $.each(self.options.colors, function(index, color) { var $clone = $dropdownItem.clone(); $clone.css("backgroundColor", color); $clone.attr("data-color", color); $dropdown.append($clone); }); } _setEvents(); return self; } /** * @method _setImage * @private */ function _setImage() { var colorPicker = new Image() , backgroundUrl = $track.css("background-image").replace(/"/g, "").replace(/url\(|\)$/ig, "") ; $track.css("background-image", "none"); $(colorPicker).load(function() { $canvas.attr("width", this.width); $canvas.attr("height", this.height); context.drawImage(colorPicker, 0, 0, this.width, this.height); }); colorPicker.src = self.options.backgroundUrl || backgroundUrl; } /** * @method _setEvents * @private */ function _setEvents() { var eventType = touchEvents ? "touchstart" : "mousedown"; if(hasCanvas) { $color.bind(eventType, function(event) { event.preventDefault(); event.stopPropagation(); $track.toggle(); $(document).bind("mousedown.colorpicker", function(event) { $(document).unbind(".colorpicker"); $track.hide(); }); }); if(!touchEvents) { $canvas.mousedown(function(event) { mouseIsDown = true; _getColorCanvas(event); $(document).bind("mouseup.colorpicker", function(event) { mouseIsDown = false; $(document).unbind(".colorpicker"); $track.hide(); return false; }); return false; }); $canvas.mousemove(_getColorCanvas); } else { $canvas.bind("touchstart", function(event) { mouseIsDown = true; _getColorCanvas(event.originalEvent.touches[0]); return false; }); $canvas.bind("touchmove", function(event) { _getColorCanvas(event.originalEvent.touches[0]); return false; }); $canvas.bind("touchend", function(event) { mouseIsDown = false; $track.hide(); return false; }); } } else { $color.bind("mousedown", function(event) { event.preventDefault(); event.stopPropagation(); $dropdown.toggle(); }); $dropdown.delegate("li", "mousedown", function(event) { event.preventDefault(); event.stopImmediatePropagation(); var color = $(this).attr("data-color"); self.setColor(color); $dropdown.hide(); }); } } /** * @method _getColorCanvas * @private */ function _getColorCanvas(event) { if(mouseIsDown) { var $target = $(event.target) , offset = $target.offset() , colorData = context.getImageData(event.pageX - offset.left, event.pageY - offset.top, 1, 1).data ; self.setColor("rgb(" + colorData[0] + "," + colorData[1] + "," + colorData[2] + ")"); /** * The change event will trigger when a new color is set. * * @event change */ $container.trigger("change", [self.colorHex, self.colorRGB]); } } /** * Set the color to a given hex or rgb color. * * @method setColor * @chainable */ this.setColor = function(color) { if(color.indexOf("#") >= 0) { self.colorHex = color; self.colorRGB = self.hexToRgb(self.colorHex); } else { self.colorRGB = color; self.colorHex = self.rgbToHex(self.colorRGB); } $color.find(".colorInner").css("backgroundColor", self.colorHex); $colorInput.val(self.colorHex); }; /** * Convert hex to rgb * * @method hexToRgb * @chainable */ this.hexToRgb = function(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return "rgb(" + parseInt(result[1], 16) + "," + parseInt(result[2], 16) + "," + parseInt(result[3], 16) + ")"; }; /** * Convert rgb to hex * * @method rgbToHex * @chainable */ this.rgbToHex = function(rgb) { var result = rgb.match(/\d+/g); function hex(x) { var digits = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"); return isNaN(x) ? "00" : digits[(x - x % 16 ) / 16] + digits[x % 16]; } return "#" + hex(result[0]) + hex(result[1]) + hex(result[2]); }; return _initialize(); } /** * @class tinycolorpicker * @constructor * @param {Object} options @param {Array} [options.colors=[]] fallback colors for old browsers (ie8-). @param {String} [options.backgroundUrl=''] It will look for a css image on the track div. If not found it will look if there's a url in this property. */ $.fn[pluginName] = function(options) { return this.each(function() { if(!$.data(this, "plugin_" + pluginName)) { $.data(this, "plugin_" + pluginName, new Plugin($(this), options)); } }); }; }));