UNPKG

evol-colorpicker

Version:

jQuery UI widget for web color picking which looks like the one in Microsoft Office 2010.

576 lines (538 loc) 15.5 kB
/* evol-colorpicker 3.4.4 ColorPicker widget for jQuery UI https://github.com/evoluteur/colorpicker (c) 2024 Olivier Giulieri * Depends: * jquery.ui.core.js * jquery.ui.widget.js */ (function( $, undefined ) { var _idx=0, ua=window.navigator.userAgent, isIE=ua.indexOf("MSIE ")>0, _ie=isIE?'-ie':'', isMoz=isIE?false:/mozilla/.test(ua.toLowerCase()) && !/webkit/.test(ua.toLowerCase()), history=[], baseThemeColors=['ffffff','000000','eeece1','1f497d','4f81bd','c0504d','9bbb59','8064a2','4bacc6','f79646'], subThemeColors=['f2f2f2','7f7f7f','ddd9c3','c6d9f0','dbe5f1','f2dcdb','ebf1dd','e5e0ec','dbeef3','fdeada', 'd8d8d8','595959','c4bd97','8db3e2','b8cce4','e5b9b7','d7e3bc','ccc1d9','b7dde8','fbd5b5', 'bfbfbf','3f3f3f','938953','548dd4','95b3d7','d99694','c3d69b','b2a2c7','92cddc','fac08f', 'a5a5a5','262626','494429','17365d','366092','953734','76923c','5f497a','31859b','e36c09', '7f7f7f','0c0c0c','1d1b10','0f243e','244061','632423','4f6128','3f3151','205867','974806'], standardColors=['c00000','ff0000','ffc000','ffff00','92d050','00b050','00b0f0','0070c0','002060','7030a0'], webColors=[ ['003366','336699','3366cc','003399','000099','0000cc','000066'], ['006666','006699','0099cc','0066cc','0033cc','0000ff','3333ff','333399'], ['669999','009999','33cccc','00ccff','0099ff','0066ff','3366ff','3333cc','666699'], ['339966','00cc99','00ffcc','00ffff','33ccff','3399ff','6699ff','6666ff','6600ff','6600cc'], ['339933','00cc66','00ff99','66ffcc','66ffff','66ccff','99ccff','9999ff','9966ff','9933ff','9900ff'], ['006600','00cc00','00ff00','66ff99','99ffcc','ccffff','ccccff','cc99ff','cc66ff','cc33ff','cc00ff','9900cc'], ['003300','009933','33cc33','66ff66','99ff99','ccffcc','ffffff','ffccff','ff99ff','ff66ff','ff00ff','cc00cc','660066'], ['333300','009900','66ff33','99ff66','ccff99','ffffcc','ffcccc','ff99cc','ff66cc','ff33cc','cc0099','993399'], ['336600','669900','99ff33','ccff66','ffff99','ffcc99','ff9999','ff6699','ff3399','cc3399','990099'], ['666633','99cc00','ccff33','ffff66','ffcc66','ff9966','ff6666','ff0066','d60094','993366'], ['a58800','cccc00','ffff00','ffcc00','ff9933','ff6600','ff0033','cc0066','660033'], ['996633','cc9900','ff9900','cc6600','ff3300','ff0000','cc0000','990033'], ['663300','996600','cc3300','993300','990000','800000','993333'] ], transColor='#0000ffff', int2Hex=function(i){ var h=i.toString(16); if(h.length==1){ h='0'+h; } return h; }, st2Hex=function(s){ return int2Hex(Number(s)); }, int2Hex3=function(i){ var h=int2Hex(i); return h+h+h; }, toHex3=function(c){ if(c.length>10){ // IE9 var p1=1+c.indexOf('('), p2=c.indexOf(')'), cs=c.substring(p1,p2).split(','); return ['#',st2Hex(cs[0]),st2Hex(cs[1]),st2Hex(cs[2])].join(''); }else{ return c; } }; $.widget( "evol.colorpicker", { version: '3.4.0', options: { color: null, // example:'#31859B' customTheme: null, // example: ["#ff0000", "#00ff00", "blue"], showOn: 'both', // possible values: 'focus','button','both' hideButton: false, displayIndicator: true, transparentColor: false, history: true, defaultPalette: 'theme', // possible values: 'theme', 'web' strings: 'Theme Colors,Standard Colors,Web Colors,Theme Colors,Back to Palette,History,No history yet.' }, // this is only true while showing the palette until color is chosen _active: false, _create: function() { var that=this; var color=this.options.color; this._paletteIdx=this.options.defaultPalette=='theme'?1:2; this._id='evo-cp'+_idx++; this._enabled=true; this.options.showOn=this.options.hideButton?'focus':this.options.showOn; switch(this.element.get(0).tagName){ case 'INPUT': var e=this.element, css=((this.options.showOn==='focus')?'':'evo-pointer ')+'evo-colorind'+(isMoz?'-ff':_ie)+(this.options.hideButton?' evo-hidden-button':''), style=''; this._isPopup=true; this._palette=null; var v=e.val(); if(color!==null){ if(color != v) e.val(color).change(); }else if(v!==''){ color=this.options.color=v; } if(color===transColor){ css+=' evo-transparent'; }else{ style=(color!==null)?('background-color:'+color):''; } e.addClass('colorPicker '+this._id) .wrap('<div style="width:'+(this.options.hideButton?this.element.width():this.element.width()+32)+'px;'+ (isIE?'margin-bottom:-21px;':'')+ (isMoz?'padding:1px 0;':'')+ '" class="evo-cp-wrap"></div>') .after('<div class="'+css+'" style="'+style+'"></div>') .on('keyup onpaste', function(evt){ var c=$(this).val(); if(c!=that.options.color){ that._setValue(c, true); } }); var showOn=this.options.showOn; if(showOn==='both' || showOn==='focus'){ e.on('focus', function(){ that.showPalette(); }); } if(showOn==='both' || showOn==='button'){ e.next().on('click', function(evt){ evt.stopPropagation(); that.showPalette(); return false; }); } break; default: this._isPopup=false; this._palette=this.element.html(this._paletteHTML()) .attr('aria-haspopup','true'); this._bindColors(); } if(this.options.history){ if(color){ this._add2History(color); } var c = this.options.initialHistory; if(c){ for (var i in c){ this._add2History(c[i]); } } } }, _paletteHTML: function() { var pIdx=this._paletteIdx=Math.abs(this._paletteIdx), opts=this.options, labels=opts.strings.split(','); var h='<div class="evo-pop'+_ie+' ui-widget ui-widget-content ui-corner-all"'+ (this._isPopup?' style="position:absolute"':'')+'>'+ // palette '<span>'+this['_paletteHTML'+pIdx]()+'</span>'+ // links '<div class="evo-more"><a href="javascript:void(0)">'+labels[1+pIdx]+'</a>'; if(opts.history){ h+='<a href="javascript:void(0)" class="evo-hist">'+labels[5]+'</a>'; } h+='</div>'; // indicator if(opts.displayIndicator){ h+=this._colorIndHTML(this.options.color)+this._colorIndHTML(''); } h+='</div>'; return h; }, _colorIndHTML: function(c) { var css=isIE?'evo-colorbox-ie ':'', style=''; if(c){ if(c===transColor){ css+='evo-transparent'; }else{ style='background-color:'+c; } }else{ style='display:none'; } return '<div class="evo-color" style="float:left">'+ '<div style="'+style+'" class="'+css+'"></div><span>'+ // class="evo-colortxt-ie" (c?c:'')+'</span></div>'; }, _paletteHTML1: function() { var opts=this.options, labels=opts.strings.split(','), oTD='<td style="background-color:', cTD=isIE?'"><div style="width:2px;"></div></td>':'"><span></span></td>', oTRTH='<tr><th colspan="10" class="ui-widget-content">', i, css='evo-palette'+_ie + (opts.customTheme ? ' cust-theme':''); var h='<table class="'+css+'">'+oTRTH+labels[0]+'</th></tr><tr>'; if (opts.customTheme) { for (i=0, ml=opts.customTheme.length;i<ml;i++) { h+=oTD+opts.customTheme[i]+cTD; if(i%10===9){ h+='</tr><tr>'; } } } else { oTD+='#'; // base theme colors for(i=0;i<10;i++){ h+=oTD+baseThemeColors[i]+cTD; } h+='</tr>'; if(!isIE){ h+='<tr><th colspan="10"></th></tr>'; } h+='<tr class="top">'; // theme colors for(i=0;i<10;i++){ h+=oTD+subThemeColors[i]+cTD; } for(var r=1;r<4;r++){ h+='</tr><tr class="in">'; for(i=0;i<10;i++){ h+=oTD+subThemeColors[r*10+i]+cTD; } } h+='</tr><tr class="bottom">'; for(i=40;i<50;i++){ h+=oTD+subThemeColors[i]+cTD; } h+='</tr>'+oTRTH; // transparent color if(opts.transparentColor){ h+='<div class="evo-transparent evo-tr-box"></div>'; } h+=labels[1]+'</th></tr><tr>'; // standard colors for(i=0;i<10;i++){ h+=oTD+standardColors[i]+cTD; } } h+='</tr></table>'; return h; }, _paletteHTML2: function() { var i, iMax, oTD='<td style="background-color:#', cTD=isIE?'"><div style="width:5px;"></div></td>':'"><span></span></td>', oTableTR='<table class="evo-palette2'+_ie+'"><tr>', cTableTR='</tr></table>'; var h='<div class="evo-palcenter">'; // hexagon colors for(var r=0,rMax=webColors.length;r<rMax;r++){ h+=oTableTR; var cs=webColors[r]; for(i=0,iMax=cs.length;i<iMax;i++){ h+=oTD+cs[i]+cTD; } h+=cTableTR; } h+='<div class="evo-sep"></div>'; // gray scale colors var h2=''; h+=oTableTR; for(i=255;i>10;i-=10){ h+=oTD+int2Hex3(i)+cTD; i-=10; h2+=oTD+int2Hex3(i)+cTD; } h+=cTableTR+oTableTR+h2+cTableTR+'</div>'; return h; }, _switchPalette: function(link) { if(this._enabled){ var idx, content, label, opts=this.options, labels=opts.strings.split(','); if($(link).hasClass('evo-hist')){ // history var h='<table class="evo-palette"><tr><th class="ui-widget-content">'+ labels[5]+'</th></tr></tr></table>'+ '<div class="evo-cHist">'; if(history.length===0){ h+='<p>&nbsp;'+labels[6]+'</p>'; }else{ for(var i=history.length-1;i>-1;i--){ if(history[i].length===9){ if(opts.transparentColor){ h+='<div class="evo-transparent"></div>'; } }else{ h+='<div style="background-color:'+history[i]+'"></div>'; } } } h+='</div>'; idx=-this._paletteIdx; content=h; label=labels[4]; }else{ // palette if(this._paletteIdx<0){ idx=-this._paletteIdx; this._palette.find('.evo-hist').show(); }else{ idx=(this._paletteIdx==2)?1:2; } content=this['_paletteHTML'+idx](); label=labels[idx+1]; this._paletteIdx=idx; } this._paletteIdx=idx; var e=this._palette.find('.evo-more') .prev().html(content).end() .children().eq(0).html(label); if(idx<0){ e.next().hide(); } } }, _downOrUpPositioning: function() { var el = this.element, i = 0; while (el !== null && i < 100) { // Look up the first parent with non-visibile overflow and compute the relative position if (el.css('overflow') != 'visible') { var bott = this._palette.offset().top + this._palette.height(), pBott = el.offset().top + el.height(), top = this._palette.offset().top - this._palette.height() - this.element.outerHeight(), pTop = el.offset().top, openUp = bott > pBott && top > pTop; if (openUp) { this._palette.css({ bottom: this.element.outerHeight()+'px' }); } else { this._palette.css({ bottom: 'auto' }); } break; } if (el[0].tagName == 'HTML') break; else el = el.offsetParent(); i++; } }, showPalette: function() { if(this._enabled){ this._active=true; $('.colorPicker').not('.'+this._id).colorpicker('hidePalette'); if(this._palette===null){ this._palette=this.element.next() .after(this._paletteHTML()).next() .on('click',function(evt){ evt.stopPropagation(); return false; }); this._bindColors(); var that=this; if(this._isPopup){ this._downOrUpPositioning(); $(document.body).on('click.'+that._id, function(evt){ if(evt.target!=that.element.get(0)){ that.hidePalette(); } }).on('keyup.'+that._id, function(evt){ if(evt.keyCode===27){ that.hidePalette(); } }); } } } return this; }, hidePalette: function() { if(this._isPopup && this._palette){ $(document.body).off('click.'+this._id); var that=this; this._palette.off('mouseover click', 'td,.evo-transparent') .fadeOut(function(){ that._palette.remove(); that._palette=that._cTxt=null; }) .find('.evo-more a').off('click'); } return this; }, _bindColors: function() { var that=this, opts=this.options, es=this._palette.find('div.evo-color'), sel=opts.history?'td,.evo-cHist>div':'td'; if(opts.transparentColor){ sel+=',.evo-transparent'; } this._cTxt1=es.eq(0).children().eq(0); this._cTxt2=es.eq(1).children().eq(0); this._palette .on('click', sel, function(evt){ if(that._enabled){ var $this=$(this); that._setValue($this.hasClass('evo-transparent')?transColor:toHex3($this.attr('style').substring(17))); that._active=false; } }) .on('mouseover', sel, function(evt){ if(that._enabled){ var $this=$(this), c=$this.hasClass('evo-transparent')?transColor:toHex3($this.attr('style').substring(17)); if(that.options.displayIndicator){ that._setColorInd(c,2); } if(that._active){ that.element.trigger('mouseover.color', c); } } }) .find('.evo-more a').on('click', function(){ that._switchPalette(this); return false; // otherwise IE10 will fire onbeforeunload event @see https://stackoverflow.com/questions/10548614/anchor-javascriptvoid0-causing-window-onbeforeunload-to-fire-on-ie }); }, val: function(value) { if (typeof value=='undefined') { return this.options.color; }else{ this._setValue(value); return this; } }, _setValue: function(c, noHide) { c = c.replace(/ /g,''); this.options.color=c; if(this._isPopup){ if(!noHide){ this.hidePalette(); } this._setBoxColor(this.element.val(c).change().next(), c); }else{ this._setColorInd(c,1); } if(this.options.history && this._paletteIdx>0){ this._add2History(c); } this.element.trigger('change.color', c); }, _setColorInd: function(c, idx) { var $box=this['_cTxt'+idx]; this._setBoxColor($box, c); $box.next().html(c); }, _setBoxColor: function($box, c) { if(c===transColor){ $box.addClass('evo-transparent') .removeAttr('style'); }else{ $box.removeClass('evo-transparent') .attr('style','background-color:'+c); } }, _setOption: function(key, value) { if(key=='color'){ this._setValue(value, true); }else{ this.options[key]=value; } }, _add2History: function(c) { var iMax=history.length; // skip color if already in history for(var i=0;i<iMax;i++){ if(c==history[i]){ return; } } // limit of 28 colors in history if(iMax>27){ history.shift(); } // add to history history.push(c); }, clear: function(){ this.hidePalette().val(''); }, enable: function() { var e=this.element; if(this._isPopup){ e.removeAttr('disabled'); }else{ e.css({ 'opacity': '1', 'pointer-events': 'auto' }); } if(this.options.showOn!=='focus'){ this.element.next().addClass('evo-pointer'); } e.removeAttr('aria-disabled'); this._enabled=true; return this; }, disable: function() { var e=this.element; if(this._isPopup){ e.attr('disabled', 'disabled'); }else{ this.hidePalette(); e.css({ 'opacity': '0.3', 'pointer-events': 'none' }); } if(this.options.showOn!=='focus'){ this.element.next().removeClass('evo-pointer'); } e.attr('aria-disabled','true'); this._enabled=false; return this; }, isDisabled: function() { return !this._enabled; }, destroy: function() { $(document.body).off('click.'+this._id); if(this._palette){ this._palette.off('mouseover click', 'td,.evo-cHist>div,.evo-transparent') .find('.evo-more a').off('click'); if(this._isPopup){ this._palette.remove(); } this._palette=this._cTxt=null; } if(this._isPopup){ this.element .next().off('click').remove() .end().off('focus').unwrap(); } this.element.removeClass('colorPicker '+this.id).empty(); $.Widget.prototype.destroy.call(this); } }); })(jQuery);