/* colpick Color Picker / colpick.com Copyright 2013 Jose Vargas. Licensed under GPL license. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Based on Stefan Petre's Color Picker www.eyecon.ro, dual licensed under the MIT and GPL licenses */ (function ($) { var colpick = function () { var tpl = '
#
R
G
B
H
S
B
', defaults = { showEvent: 'click', onShow: function () {}, onBeforeShow: function(){}, onHide: function () {}, onChange: function () {}, onSubmit: function () {}, colorScheme: 'light', color: '11ff00', livePreview: true, flat: false, layout: 'full', submit: 1, submitText: 'OK', height: 150 }, //Fill the inputs of the plugin fillRGBFields = function (hsb, cal) { var rgb = HSBToRGB(hsb); $(cal).data('colpick').fields .eq(1).val(rgb.r).end() .eq(2).val(rgb.g).end() .eq(3).val(rgb.b).end(); }, fillHSBFields = function (hsb, cal) { $(cal).data('colpick').fields .eq(4).val(Math.round(hsb.h*10)/10).end() .eq(5).val(Math.round(hsb.s*10)/10).end() .eq(6).val(Math.round(hsb.b*10)/10).end(); }, fillHexFields = function (hsb, cal) { $(cal).data('colpick').fields.eq(0).val(HSBToHex(hsb)); }, //Set the round selector position setSelector = function (hsb, cal) { $(cal).data('colpick').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100})); $(cal).data('colpick').selectorIndic.css({ left: parseInt($(cal).data('colpick').height * hsb.s/100, 10), top: parseInt($(cal).data('colpick').height * (100-hsb.b)/100, 10) }); }, //Set the hue selector position setHue = function (hsb, cal) { $(cal).data('colpick').hue.css('top', parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h/360, 10)); }, //Set current and new colors setCurrentColor = function (hsb, cal) { $(cal).data('colpick').currentColor.css('backgroundColor', '#' + HSBToHex(hsb)); }, setNewColor = function (hsb, cal) { $(cal).data('colpick').newColor.css('backgroundColor', '#' + HSBToHex(hsb)); }, //Function called when the new color is changed change = function (ev) { var cal = $(this).parent().parent(), col; if (this.parentNode.className.indexOf('_hex') > 0) { cal.data('colpick').color = col = HexToHSB(fixHex(this.value)); } else if (this.parentNode.className.indexOf('_hsb') > 0) { cal.data('colpick').color = col = fixHSB({ h: parseInt(cal.data('colpick').fields.eq(4).val(), 10), s: parseInt(cal.data('colpick').fields.eq(5).val(), 10), b: parseInt(cal.data('colpick').fields.eq(6).val(), 10) }); } else { cal.data('colpick').color = col = RGBToHSB(fixRGB({ r: parseInt(cal.data('colpick').fields.eq(1).val(), 10), g: parseInt(cal.data('colpick').fields.eq(2).val(), 10), b: parseInt(cal.data('colpick').fields.eq(3).val(), 10) })); } if (ev) { fillRGBFields(col, cal.get(0)); fillHexFields(col, cal.get(0)); fillHSBFields(col, cal.get(0)); } setSelector(col, cal.get(0)); setHue(col, cal.get(0)); setNewColor(col, cal.get(0)); cal.data('colpick').onChange.apply(cal.parent(), [col, HSBToHex(col), HSBToRGB(col)]); }, //Change style on blur and focus of inputs blur = function (ev) { $(this).parent().removeClass('colpick_focus'); }, focus = function () { $(this).parent().parent().data('colpick').fields.parent().removeClass('colpick_focus'); $(this).parent().addClass('colpick_focus'); }, //Increment/decrement arrows next to the fields downIncrement = function (ev) { var field = $(this).parent().find('input').focus(); var current = { el: $(this).parent().addClass('colpick_slider'), max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), y: ev.pageY, field: field, val: parseInt(field.val(), 10), preview: $(this).parent().parent().data('colpick').livePreview }; $(document).mouseup(current, upIncrement); $(document).mousemove(current, moveIncrement); }, moveIncrement = function (ev) { ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val - ev.pageY + ev.data.y, 10)))); if (ev.data.preview) { change.apply(ev.data.field.get(0), [true]); } return false; }, upIncrement = function (ev) { change.apply(ev.data.field.get(0), [true]); ev.data.el.removeClass('colpick_slider').find('input').focus(); $(document).off('mouseup', upIncrement); $(document).off('mousemove', moveIncrement); return false; }, //Hue slider functions downHue = function (ev) { var current = { cal: $(this).parent(), y: $(this).offset().top }; current.preview = current.cal.data('colpick').livePreview; $(document).mouseup(current, upHue); $(document).mousemove(current, moveHue); change.apply( current.cal.data('colpick') .fields.eq(4).val(parseInt(360*(current.cal.data('colpick').height - (ev.pageY - current.y))/current.cal.data('colpick').height, 10)) .get(0), [current.preview] ); }, moveHue = function (ev) { change.apply( ev.data.cal.data('colpick') .fields.eq(4).val(parseInt(360*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(ev.pageY - ev.data.y))))/ev.data.cal.data('colpick').height, 10)) .get(0), [ev.data.preview] ); return false; }, upHue = function (ev) { fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); $(document).off('mouseup', upHue); $(document).off('mousemove', moveHue); return false; }, //Color selector functions downSelector = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; //Get colpick and position of the selector var current = { cal: $(this).parent(), pos: $(this).offset() }; current.preview = current.cal.data('colpick').livePreview; $(document).mouseup(current, upSelector); $(document).mousemove(current, moveSelector); change.apply( current.cal.data('colpick').fields .eq(6).val(parseInt(100*(current.cal.data('colpick').height - (ev.pageY - current.pos.top))/current.cal.data('colpick').height, 10)).end() .eq(5).val(parseInt(100*(ev.pageX - current.pos.left)/current.cal.data('colpick').height, 10)) .get(0), [current.preview] ); }, moveSelector = function (ev) { change.apply( ev.data.cal.data('colpick').fields .eq(6).val(parseInt(100*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(ev.pageY - ev.data.pos.top))))/ev.data.cal.data('colpick').height, 10)).end() .eq(5).val(parseInt(100*(Math.max(0,Math.min(ev.data.cal.data('colpick').height,(ev.pageX - ev.data.pos.left))))/ev.data.cal.data('colpick').height, 10)) .get(0), [ev.data.preview] ); return false; }, upSelector = function (ev) { fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0)); $(document).off('mouseup', upSelector); $(document).off('mousemove', moveSelector); return false; }, //Submit button clickSubmit = function (ev) { var cal = $(this).parent(); var col = cal.data('colpick').color; cal.data('colpick').origColor = col; setCurrentColor(col, cal.get(0)); cal.data('colpick').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colpick').el); }, //Show/hide the color picker show = function (ev) { var cal = $('#' + $(this).data('colpickId')); cal.data('colpick').onBeforeShow.apply(this, [cal.get(0)]); var pos = $(this).offset(); var top = pos.top + this.offsetHeight; var left = pos.left; var viewPort = getViewport(); if (left + 346 > viewPort.l + viewPort.w) { left -= 346; } cal.css({left: left + 'px', top: top + 'px'}); if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) != false) { cal.show(); } //Hide when user clicks outside $('html').mousedown({cal:cal}, hide); cal.mousedown(function(ev){ev.stopPropagation();}) return false; }, hide = function (ev) { if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) != false) { ev.data.cal.hide(); } $('html').off('mousedown', hide); return false; }, getViewport = function () { var m = document.compatMode == 'CSS1Compat'; return { l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth), }; }, //Fix the values if the user enters a negative or high value fixHSB = function (hsb) { return { h: Math.min(360, Math.max(0, hsb.h)), s: Math.min(100, Math.max(0, hsb.s)), b: Math.min(100, Math.max(0, hsb.b)) }; }, fixRGB = function (rgb) { return { r: Math.min(255, Math.max(0, rgb.r)), g: Math.min(255, Math.max(0, rgb.g)), b: Math.min(255, Math.max(0, rgb.b)) }; }, fixHex = function (hex) { var len = 6 - hex.length; if (len > 0) { var o = []; for (var i=0; i -1) ? hex.substring(1) : hex), 16); return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)}; }, HexToHSB = function (hex) { return RGBToHSB(HexToRGB(hex)); }, RGBToHSB = function (rgb) { var hsb = { h: 0, s: 0, b: 0 }; var min = Math.min(rgb.r, rgb.g, rgb.b); var max = Math.max(rgb.r, rgb.g, rgb.b); var delta = max - min; hsb.b = max; if (max != 0) { } hsb.s = max != 0 ? 255 * delta / max : 0; if (hsb.s != 0) { if (rgb.r == max) { hsb.h = (rgb.g - rgb.b) / delta; } else if (rgb.g == max) { hsb.h = 2 + (rgb.b - rgb.r) / delta; } else { hsb.h = 4 + (rgb.r - rgb.g) / delta; } } else { hsb.h = -1; } hsb.h *= 60; if (hsb.h < 0) { hsb.h += 360; } hsb.s *= 100/255; hsb.b *= 100/255; return hsb; }, HSBToRGB = function (hsb) { var rgb = {}; var h = Math.round(hsb.h); var s = Math.round(hsb.s*255/100); var v = Math.round(hsb.b*255/100); if(s == 0) { rgb.r = rgb.g = rgb.b = v; } else { var t1 = v; var t2 = (255-s)*v/255; var t3 = (t1-t2)*(h%60)/60; if(h==360) h = 0; if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} else {rgb.r=0; rgb.g=0; rgb.b=0} } return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; }, RGBToHex = function (rgb) { var hex = [ rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16) ]; $.each(hex, function (nr, val) { if (val.length == 1) { hex[nr] = '0' + val; } }); return hex.join(''); }, HSBToHex = function (hsb) { return RGBToHex(HSBToRGB(hsb)); }, restoreOriginal = function () { var cal = $(this).parent(); var col = cal.data('colpick').origColor; cal.data('colpick').color = col; fillRGBFields(col, cal.get(0)); fillHexFields(col, cal.get(0)); fillHSBFields(col, cal.get(0)); setSelector(col, cal.get(0)); setHue(col, cal.get(0)); setNewColor(col, cal.get(0)); }; return { init: function (opt) { opt = $.extend({}, defaults, opt||{}); //Set color if (typeof opt.color == 'string') { opt.color = HexToHSB(opt.color); } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) { opt.color = RGBToHSB(opt.color); } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) { opt.color = fixHSB(opt.color); } else { return this; } //For each selected DOM element return this.each(function () { //If the element does not have an ID if (!$(this).data('colpickId')) { var options = $.extend({}, opt); options.origColor = opt.color; //Generate and assign a random ID var id = 'collorpicker_' + parseInt(Math.random() * 1000); $(this).data('colpickId', id); //Set the tpl's ID and get the HTML var cal = $(tpl).attr('id', id); //Add class according to layout cal.addClass('colpick_'+options.layout+(options.submit?'':' colpick_'+options.layout+'_ns')); //Add class if the color scheme is not dark(default) if(options.colorScheme != 'light') { cal.addClass('colpick_'+options.colorScheme); } //Setup submit button cal.find('div.colpick_submit').html(options.submitText).click(clickSubmit); //Setup input fields options.fields = cal.find('input').change(change).blur(blur).focus(focus); cal.find('span').mousedown(downIncrement).end().find('>div.colpick_current_color').click(restoreOriginal); //Setup hue selector options.selector = cal.find('div.colpick_color').mousedown(downSelector); options.selectorIndic = options.selector.find('div div'); //Store parts of the plugin options.el = this; options.hue = cal.find('div.colpick_hue div'); cal.find('div.colpick_hue').mousedown(downHue); options.newColor = cal.find('div.colpick_new_color'); options.currentColor = cal.find('div.colpick_current_color'); //Store options and fill with default color cal.data('colpick', options); fillRGBFields(options.color, cal.get(0)); fillHSBFields(options.color, cal.get(0)); fillHexFields(options.color, cal.get(0)); setHue(options.color, cal.get(0)); setSelector(options.color, cal.get(0)); setCurrentColor(options.color, cal.get(0)); setNewColor(options.color, cal.get(0)); //Append to the body if flat=false, else show in place if (options.flat) { cal.appendTo(this).show(); cal.css({ position: 'relative', display: 'block' }); } else { cal.appendTo(document.body); $(this).on(options.showEvent, show); cal.css({ position:'absolute' }); } } }); }, //colpickShow showPicker: function() { return this.each( function () { if ($(this).data('colpickId')) { show.apply(this); } }); }, //colpickHide hidePicker: function() { return this.each( function () { if ($(this).data('colpickId')) { $('#' + $(this).data('colpickId')).hide(); } }); }, //colpickSetColor setColor: function(col) { if (typeof col == 'string') { col = HexToHSB(col); } else if (col.r != undefined && col.g != undefined && col.b != undefined) { col = RGBToHSB(col); } else if (col.h != undefined && col.s != undefined && col.b != undefined) { col = fixHSB(col); } else { return this; } return this.each(function(){ if ($(this).data('colpickId')) { var cal = $('#' + $(this).data('colpickId')); cal.data('colpick').color = col; cal.data('colpick').origColor = col; fillRGBFields(col, cal.get(0)); fillHSBFields(col, cal.get(0)); fillHexFields(col, cal.get(0)); setHue(col, cal.get(0)); setSelector(col, cal.get(0)); setCurrentColor(col, cal.get(0)); setNewColor(col, cal.get(0)); } }); } }; }(); $.fn.extend({ colpick: colpick.init, colpickHide: colpick.hidePicker, colpickShow: colpick.showPicker, colpickSetColor: colpick.setColor }); })(jQuery)