spectrum-rails 1.2.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e0056a77b0e6e14c395beae83632e947cdba7740889850cf387b0760fd0780ec
4
+ data.tar.gz: 95a6f7caa9446684f05cb7fae3d69e07f2b05c19e838ae3cb3ee89d78e13f85d
5
+ SHA512:
6
+ metadata.gz: 343a9444e178da55a8a91f8a949f7b6877b27d9d011c6d3f015edce7689069ea78df903ac1245a02e82c64dafc22a74a2900facb8a657bd4f40cc574118e2786
7
+ data.tar.gz: 974f376b3d4e7e9603f1a1124b88450d84e9490e75c46b790acbc9e9e3451bfe96d765c122db485b19f4a0968a3fa27fd9a6c2f52ebd6bfcedc5fe0fa0f4da15
@@ -1,5 +1,5 @@
1
1
  module Spectrum
2
2
  module Rails
3
- VERSION = "1.2.0"
3
+ VERSION = "1.8.1"
4
4
  end
5
5
  end
@@ -0,0 +1 @@
1
+ !function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports&&"object"==typeof module?module.exports=t(require("jquery")):t(jQuery)}(function(jt,Et){"use strict";var t,Dt={beforeShow:r,move:r,change:r,show:r,hide:r,color:!1,flat:!1,showInput:!1,allowEmpty:!1,showButtons:!0,clickoutFiresChange:!0,showInitial:!1,showPalette:!1,showPaletteOnly:!1,hideAfterPaletteSelect:!1,togglePaletteOnly:!1,showSelectionPalette:!0,localStorageKey:!1,appendTo:"body",maxSelectionSize:7,cancelText:"cancel",chooseText:"choose",togglePaletteMoreText:"more",togglePaletteLessText:"less",clearText:"Clear Color Selection",noColorSelectedText:"No Color Selected",preferredFormat:!1,className:"",containerClassName:"",replacerClassName:"",showAlpha:!1,theme:"sp-light",palette:[["#ffffff","#000000","#ff0000","#ff8000","#ffff00","#008000","#0000ff","#4b0082","#9400d3"]],selectionPalette:[],disabled:!1,offset:null},It=[],zt=!!/msie/i.exec(window.navigator.userAgent),Bt=((t=document.createElement("div").style).cssText="background-color:rgba(0,0,0,.5)",e(t.backgroundColor,"rgba")||e(t.backgroundColor,"hsla")),Lt=["<div class='sp-replacer'>","<div class='sp-preview'><div class='sp-preview-inner'></div></div>","<div class='sp-dd'>&#9660;</div>","</div>"].join(""),Kt=function(){var t="";if(zt)for(var e=1;e<=6;e++)t+="<div class='sp-"+e+"'></div>";return["<div class='sp-container sp-hidden'>","<div class='sp-palette-container'>","<div class='sp-palette sp-thumb sp-cf'></div>","<div class='sp-palette-button-container sp-cf'>","<button type='button' class='sp-palette-toggle'></button>","</div>","</div>","<div class='sp-picker-container'>","<div class='sp-top sp-cf'>","<div class='sp-fill'></div>","<div class='sp-top-inner'>","<div class='sp-color'>","<div class='sp-sat'>","<div class='sp-val'>","<div class='sp-dragger'></div>","</div>","</div>","</div>","<div class='sp-clear sp-clear-display'>","</div>","<div class='sp-hue'>","<div class='sp-slider'></div>",t,"</div>","</div>","<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>","</div>","<div class='sp-input-container sp-cf'>","<input class='sp-input' type='text' spellcheck='false' />","</div>","<div class='sp-initial sp-thumb sp-cf'></div>","<div class='sp-button-container sp-cf'>","<a class='sp-cancel' href='#'></a>","<button type='button' class='sp-choose'></button>","</div>","</div>","</div>"].join("")}();function e(t,e){return!!~(""+t).indexOf(e)}function Vt(t,e,r,a){for(var n=[],o=0;o<t.length;o++){var i,s,l,c,f=t[o];f?(s=(i=tinycolor(f)).toHsl().l<.5?"sp-thumb-el sp-thumb-dark":"sp-thumb-el sp-thumb-light",s+=tinycolor.equals(e,f)?" sp-thumb-active":"",l=i.toString(a.preferredFormat||"rgb"),c=Bt?"background-color:"+i.toRgbString():"filter:"+i.toFilter(),n.push('<span title="'+l+'" data-color="'+i.toRgbString()+'" class="'+s+'"><span class="sp-thumb-inner" style="'+c+';"></span></span>')):n.push(jt("<div />").append(jt('<span data-color="" style="background-color:transparent;" class="sp-clear-display"></span>').attr("title",a.noColorSelectedText)).html())}return"<div class='sp-cf "+r+"'>"+n.join("")+"</div>"}function o(t,e){var r,a,n,o,i,s,l,u=(i=e,s=t,(l=jt.extend({},Dt,i)).callbacks={move:Wt(l.move,s),change:Wt(l.change,s),show:Wt(l.show,s),hide:Wt(l.hide,s),beforeShow:Wt(l.beforeShow,s)},l),d=u.flat,c=u.showSelectionPalette,f=u.localStorageKey,h=u.theme,p=u.callbacks,g=(r=Ot,function(){var t=this,e=arguments;n&&clearTimeout(o),!n&&o||(o=setTimeout(function(){o=null,r.apply(t,e)},a))}),b=!(a=10),v=!1,m=0,y=0,w=0,_=0,x=0,k=0,S=0,C=0,P=0,A=0,M=1,R=[],H=[],F={},T=u.selectionPalette.slice(0),O=u.maxSelectionSize,q="sp-dragging",N=null,j=t.ownerDocument,E=(j.body,jt(t)),D=!1,I=jt(Kt,j).addClass(h),z=I.find(".sp-picker-container"),B=I.find(".sp-color"),L=I.find(".sp-dragger"),K=I.find(".sp-hue"),V=I.find(".sp-slider"),$=I.find(".sp-alpha-inner"),W=I.find(".sp-alpha"),X=I.find(".sp-alpha-handle"),Y=I.find(".sp-input"),G=I.find(".sp-palette"),Q=I.find(".sp-initial"),J=I.find(".sp-cancel"),U=I.find(".sp-clear"),Z=I.find(".sp-choose"),tt=I.find(".sp-palette-toggle"),et=E.is("input"),rt=et&&"color"===E.attr("type")&&Yt(),at=et&&!d,nt=at?jt(Lt).addClass(h).addClass(u.className).addClass(u.replacerClassName):jt([]),ot=at?nt:E,it=nt.find(".sp-preview-inner"),st=u.color||et&&E.val(),lt=!1,ct=u.preferredFormat,ft=!u.showButtons||u.clickoutFiresChange,ht=!st,ut=u.allowEmpty&&!rt;function dt(){if(u.showPaletteOnly&&(u.showPalette=!0),tt.text(u.showPaletteOnly?u.togglePaletteMoreText:u.togglePaletteLessText),u.palette){R=u.palette.slice(0),H=jt.isArray(R[0])?R:[R],F={};for(var t=0;t<H.length;t++)for(var e=0;e<H[t].length;e++){var r=tinycolor(H[t][e]).toRgbString();F[r]=!0}}I.toggleClass("sp-flat",d),I.toggleClass("sp-input-disabled",!u.showInput),I.toggleClass("sp-alpha-enabled",u.showAlpha),I.toggleClass("sp-clear-enabled",ut),I.toggleClass("sp-buttons-disabled",!u.showButtons),I.toggleClass("sp-palette-buttons-disabled",!u.togglePaletteOnly),I.toggleClass("sp-palette-disabled",!u.showPalette),I.toggleClass("sp-palette-only",u.showPaletteOnly),I.toggleClass("sp-initial-disabled",!u.showInitial),I.addClass(u.className).addClass(u.containerClassName),Ot()}function pt(){if(f&&window.localStorage){try{var t=window.localStorage[f].split(",#");1<t.length&&(delete window.localStorage[f],jt.each(t,function(t,e){gt(e)}))}catch(t){}try{T=window.localStorage[f].split(";")}catch(t){}}}function gt(t){if(c){var e=tinycolor(t).toRgbString();if(!F[e]&&-1===jt.inArray(e,T))for(T.push(e);T.length>O;)T.shift();if(f&&window.localStorage)try{window.localStorage[f]=T.join(";")}catch(t){}}}function bt(){var r=Mt(),t=jt.map(H,function(t,e){return Vt(t,r,"sp-palette-row sp-palette-row-"+e,u)});pt(),T&&t.push(Vt(function(){var t=[];if(u.showPalette)for(var e=0;e<T.length;e++){var r=tinycolor(T[e]).toRgbString();F[r]||t.push(T[e])}return t.reverse().slice(0,u.maxSelectionSize)}(),r,"sp-palette-row sp-palette-row-selection",u)),G.html(t.join(""))}function vt(){var t,e;u.showInitial&&(t=lt,e=Mt(),Q.html(Vt([t,e],e,"sp-palette-row-initial",u)))}function mt(){(y<=0||m<=0||_<=0)&&Ot(),v=!0,I.addClass(q),N=null,E.trigger("dragstart.spectrum",[Mt()])}function yt(){v=!1,I.removeClass(q),E.trigger("dragstop.spectrum",[Mt()])}function wt(){var t,e=Y.val();null!==e&&""!==e||!ut?(t=tinycolor(e)).isValid()?(At(t),Rt(),Tt()):Y.addClass("sp-validation-error"):(At(null),Rt(),Tt())}function _t(){(b?Ct:xt)()}function xt(){var t=jt.Event("beforeShow.spectrum");b?Ot():(E.trigger(t,[Mt()]),!1===p.beforeShow(Mt())||t.isDefaultPrevented()||(function(){for(var t=0;t<It.length;t++)It[t]&&It[t].hide()}(),b=!0,jt(j).on("keydown.spectrum",kt),jt(j).on("click.spectrum",St),jt(window).on("resize.spectrum",g),nt.addClass("sp-active"),I.removeClass("sp-hidden"),Ot(),Ht(),lt=Mt(),vt(),p.show(lt),E.trigger("show.spectrum",[lt])))}function kt(t){27===t.keyCode&&Ct()}function St(t){2!=t.button&&(v||(ft?Tt(!0):Pt(),Ct()))}function Ct(){b&&!d&&(b=!1,jt(j).off("keydown.spectrum",kt),jt(j).off("click.spectrum",St),jt(window).off("resize.spectrum",g),nt.removeClass("sp-active"),I.addClass("sp-hidden"),p.hide(Mt()),E.trigger("hide.spectrum",[Mt()]))}function Pt(){At(lt,!0),Tt(!0)}function At(t,e){var r,a;tinycolor.equals(t,Mt())?Ht():(!t&&ut?ht=!0:(ht=!1,a=(r=tinycolor(t)).toHsv(),C=a.h%360/360,P=a.s,A=a.v,M=a.a),Ht(),r&&r.isValid()&&!e&&(ct=u.preferredFormat||r.getFormat()))}function Mt(t){return t=t||{},ut&&ht?null:tinycolor.fromRatio({h:C,s:P,v:A,a:Math.round(1e3*M)/1e3},{format:t.format||ct})}function Rt(){Ht(),p.move(Mt()),E.trigger("move.spectrum",[Mt()])}function Ht(){Y.removeClass("sp-validation-error"),Ft();var t=tinycolor.fromRatio({h:C,s:1,v:1});B.css("background-color",t.toHexString());var e=ct;M<1&&(0!==M||"name"!==e)&&("hex"!==e&&"hex3"!==e&&"hex6"!==e&&"name"!==e||(e="rgb"));var r,a,n,o,i,s=Mt({format:e}),l="";it.removeClass("sp-clear-display"),it.css("background-color","transparent"),!s&&ut?it.addClass("sp-clear-display"):(r=s.toHexString(),a=s.toRgbString(),Bt||1===s.alpha?it.css("background-color",a):(it.css("background-color","transparent"),it.css("filter",s.toFilter())),u.showAlpha&&((n=s.toRgb()).a=0,i="linear-gradient(left, "+(o=tinycolor(n).toRgbString())+", "+r+")",zt?$.css("filter",tinycolor(o).toFilter({gradientType:1},r)):($.css("background","-webkit-"+i),$.css("background","-moz-"+i),$.css("background","-ms-"+i),$.css("background","linear-gradient(to right, "+o+", "+r+")"))),l=s.toString(e)),u.showInput&&Y.val(l),u.showPalette&&bt(),vt()}function Ft(){var t,e,r,a,n=P,o=A;ut&&ht?(X.hide(),V.hide(),L.hide()):(X.show(),V.show(),L.show(),t=n*m,e=y-o*y,t=Math.max(-w,Math.min(m-w,t-w)),e=Math.max(-w,Math.min(y-w,e-w)),L.css({top:e+"px",left:t+"px"}),r=M*x,X.css({left:r-k/2+"px"}),a=C*_,V.css({top:a-S+"px"}))}function Tt(t){var e=Mt(),r="",a=!tinycolor.equals(e,lt);e&&(r=e.toString(ct),gt(e)),et&&E.val(r),t&&a&&(p.change(e),E.trigger("change",[e]))}function Ot(){var t,e,r,a,n,o,i,s,l,c,f,h;b&&(m=B.width(),y=B.height(),w=L.height(),K.width(),_=K.height(),S=V.height(),x=W.width(),k=X.width(),d||(I.css("position","absolute"),u.offset?I.offset(u.offset):I.offset((e=ot,r=(t=I).outerWidth(),a=t.outerHeight(),n=e.outerHeight(),o=t[0].ownerDocument,i=o.documentElement,s=i.clientWidth+jt(o).scrollLeft(),l=i.clientHeight+jt(o).scrollTop(),c=e.offset(),f=c.left,h=c.top,h+=n,f-=Math.min(f,s<f+r&&r<s?Math.abs(f+r-s):0),{top:h-=Math.min(h,l<h+a&&a<l?Math.abs(+(a+n)):0),bottom:c.bottom,left:f,right:c.right,width:c.width,height:c.height}))),Ft(),u.showPalette&&bt(),E.trigger("reflow.spectrum"))}function qt(){Ct(),D=!0,E.attr("disabled",!0),ot.addClass("sp-disabled")}!function(){var t;function e(t){return t.data&&t.data.ignore?(At(jt(t.target).closest(".sp-thumb-el").data("color")),Rt()):(At(jt(t.target).closest(".sp-thumb-el").data("color")),Rt(),u.hideAfterPaletteSelect?(Tt(!0),Ct()):Tt()),!1}zt&&I.find("*:not(input)").attr("unselectable","on"),dt(),at&&E.after(nt).hide(),ut||U.hide(),d?E.after(I).hide():(1!==(t="parent"===u.appendTo?E.parent():jt(u.appendTo)).length&&(t=jt("body")),t.append(I)),pt(),ot.on("click.spectrum touchstart.spectrum",function(t){D||_t(),t.stopPropagation(),jt(t.target).is("input")||t.preventDefault()}),!E.is(":disabled")&&!0!==u.disabled||qt(),I.click($t),Y.change(wt),Y.on("paste",function(){setTimeout(wt,1)}),Y.keydown(function(t){13==t.keyCode&&wt()}),J.text(u.cancelText),J.on("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),Pt(),Ct()}),U.attr("title",u.clearText),U.on("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),ht=!0,Rt(),d&&Tt(!0)}),Z.text(u.chooseText),Z.on("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),zt&&Y.is(":focus")&&Y.trigger("change"),Y.hasClass("sp-validation-error")||(Tt(!0),Ct())}),tt.text(u.showPaletteOnly?u.togglePaletteMoreText:u.togglePaletteLessText),tt.on("click.spectrum",function(t){t.stopPropagation(),t.preventDefault(),u.showPaletteOnly=!u.showPaletteOnly,u.showPaletteOnly||d||I.css("left","-="+(z.outerWidth(!0)+5)),dt()}),Xt(W,function(t,e,r){M=t/x,ht=!1,r.shiftKey&&(M=Math.round(10*M)/10),Rt()},mt,yt),Xt(K,function(t,e){C=parseFloat(e/_),ht=!1,u.showAlpha||(M=1),Rt()},mt,yt),Xt(B,function(t,e,r){var a,n,o;r.shiftKey?N||(a=P*m,n=y-A*y,o=Math.abs(t-a)>Math.abs(e-n),N=o?"x":"y"):N=null;var i=!N||"y"===N;N&&"x"!==N||(P=parseFloat(t/m)),i&&(A=parseFloat((y-e)/y)),ht=!1,u.showAlpha||(M=1),Rt()},mt,yt),st?(At(st),Ht(),ct=u.preferredFormat||tinycolor(st).format,gt(st)):Ht(),d&&xt();var r=zt?"mousedown.spectrum":"click.spectrum touchstart.spectrum";G.on(r,".sp-thumb-el",e),Q.on(r,".sp-thumb-el:nth-child(1)",{ignore:!0},e)}();var Nt={show:xt,hide:Ct,toggle:_t,reflow:Ot,option:function(t,e){return t===Et?jt.extend({},u):e===Et?u[t]:(u[t]=e,"preferredFormat"===t&&(ct=u.preferredFormat),void dt())},enable:function(){D=!1,E.attr("disabled",!1),ot.removeClass("sp-disabled")},disable:qt,offset:function(t){u.offset=t,Ot()},set:function(t){At(t),Tt()},get:Mt,destroy:function(){E.show(),ot.off("click.spectrum touchstart.spectrum"),I.remove(),nt.remove(),It[Nt.id]=null},container:I};return Nt.id=It.push(Nt)-1,Nt}function r(){}function $t(t){t.stopPropagation()}function Wt(t,e){var r=Array.prototype.slice,a=r.call(arguments,2);return function(){return t.apply(e,a.concat(r.call(arguments)))}}function Xt(i,s,e,t){s=s||function(){},e=e||function(){},t=t||function(){};var l=document,c=!1,f={},h=0,u=0,d="ontouchstart"in window,r={};function p(t){t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),t.returnValue=!1}function a(t){if(c){if(zt&&l.documentMode<9&&!t.button)return g();var e=t.originalEvent&&t.originalEvent.touches&&t.originalEvent.touches[0],r=e&&e.pageX||t.pageX,a=e&&e.pageY||t.pageY,n=Math.max(0,Math.min(r-f.left,u)),o=Math.max(0,Math.min(a-f.top,h));d&&p(t),s.apply(i,[n,o,t])}}function g(){c&&(jt(l).off(r),jt(l.body).removeClass("sp-dragging"),setTimeout(function(){t.apply(i,arguments)},0)),c=!1}r.selectstart=p,r.dragstart=p,r["touchmove mousemove"]=a,r["touchend mouseup"]=g,jt(i).on("touchstart mousedown",function(t){(t.which?3==t.which:2==t.button)||c||!1!==e.apply(i,arguments)&&(c=!0,h=jt(i).height(),u=jt(i).width(),f=jt(i).offset(),jt(l).on(r),jt(l.body).addClass("sp-dragging"),a(t),p(t))})}function Yt(){return jt.fn.spectrum.inputTypeColorSupport()}var i="spectrum.id";jt.fn.spectrum=function(r,t){if("string"!=typeof r)return this.spectrum("destroy").each(function(){var t=o(this,jt.extend({},jt(this).data(),r));jt(this).data(i,t.id)});var a=this,n=Array.prototype.slice.call(arguments,1);return this.each(function(){var t=It[jt(this).data(i)];if(t){var e=t[r];if(!e)throw new Error("Spectrum: no such method: '"+r+"'");"get"==r?a=t.get():"container"==r?a=t.container:"option"==r?a=t.option.apply(t,n):"destroy"==r?(t.destroy(),jt(this).removeData(i)):e.apply(t,n)}}),a},jt.fn.spectrum.load=!0,jt.fn.spectrum.loadOpts={},jt.fn.spectrum.draggable=Xt,jt.fn.spectrum.defaults=Dt,jt.fn.spectrum.inputTypeColorSupport=function t(){var e;return void 0===t._cachedResult&&(e=jt("<input type='color'/>")[0],t._cachedResult="color"===e.type&&""!==e.value),t._cachedResult},jt.spectrum={},jt.spectrum.localization={},jt.spectrum.palettes={},jt.fn.spectrum.processNativeColorInputs=function(){var t=jt("input[type=color]");t.length&&!Yt()&&t.spectrum({preferredFormat:"hex6"})},function(){var o=/^[\s,#]+/,i=/\s+$/,a=0,c=Math,s=c.round,f=c.min,h=c.max,t=c.random,u=function(t,e){if(e=e||{},(t=t||"")instanceof u)return t;if(!(this instanceof u))return new u(t,e);var r=function(t){var e={r:0,g:0,b:0},r=1,a=!1,n=!1;"string"==typeof t&&(t=function(t){t=t.replace(o,"").replace(i,"").toLowerCase();var e,r=!1;if(P[t])t=P[t],r=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};if(e=E.rgb.exec(t))return{r:e[1],g:e[2],b:e[3]};if(e=E.rgba.exec(t))return{r:e[1],g:e[2],b:e[3],a:e[4]};if(e=E.hsl.exec(t))return{h:e[1],s:e[2],l:e[3]};if(e=E.hsla.exec(t))return{h:e[1],s:e[2],l:e[3],a:e[4]};if(e=E.hsv.exec(t))return{h:e[1],s:e[2],v:e[3]};if(e=E.hsva.exec(t))return{h:e[1],s:e[2],v:e[3],a:e[4]};if(e=E.hex8.exec(t))return{a:function(t){return F(t)/255}(e[1]),r:F(e[2]),g:F(e[3]),b:F(e[4]),format:r?"name":"hex8"};if(e=E.hex6.exec(t))return{r:F(e[1]),g:F(e[2]),b:F(e[3]),format:r?"name":"hex"};if(e=E.hex3.exec(t))return{r:F(e[1]+""+e[1]),g:F(e[2]+""+e[2]),b:F(e[3]+""+e[3]),format:r?"name":"hex"};return!1}(t));"object"==typeof t&&(t.hasOwnProperty("r")&&t.hasOwnProperty("g")&&t.hasOwnProperty("b")?(e=function(t,e,r){return{r:255*R(t,255),g:255*R(e,255),b:255*R(r,255)}}(t.r,t.g,t.b),a=!0,n="%"===String(t.r).substr(-1)?"prgb":"rgb"):t.hasOwnProperty("h")&&t.hasOwnProperty("s")&&t.hasOwnProperty("v")?(t.s=O(t.s),t.v=O(t.v),e=function(t,e,r){t=6*R(t,360),e=R(e,100),r=R(r,100);var a=c.floor(t),n=t-a,o=r*(1-e),i=r*(1-n*e),s=r*(1-(1-n)*e),l=a%6;return{r:255*[r,i,o,o,s,r][l],g:255*[s,r,r,i,o,o][l],b:255*[o,o,s,r,r,i][l]}}(t.h,t.s,t.v),a=!0,n="hsv"):t.hasOwnProperty("h")&&t.hasOwnProperty("s")&&t.hasOwnProperty("l")&&(t.s=O(t.s),t.l=O(t.l),e=function(t,e,r){var a,n,o;function i(t,e,r){return r<0&&(r+=1),1<r&&--r,r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t}{var s,l;t=R(t,360),e=R(e,100),r=R(r,100),0===e?a=n=o=r:(a=i(l=2*r-(s=r<.5?r*(1+e):r+e-r*e),s,t+1/3),n=i(l,s,t),o=i(l,s,t-1/3))}return{r:255*a,g:255*n,b:255*o}}(t.h,t.s,t.l),a=!0,n="hsl"),t.hasOwnProperty("a")&&(r=t.a));return r=M(r),{ok:a,format:t.format||n,r:f(255,h(e.r,0)),g:f(255,h(e.g,0)),b:f(255,h(e.b,0)),a:r}}(t);this._originalInput=t,this._r=r.r,this._g=r.g,this._b=r.b,this._a=r.a,this._roundA=s(1e3*this._a)/1e3,this._format=e.format||r.format,this._gradientType=e.gradientType,this._r<1&&(this._r=s(this._r)),this._g<1&&(this._g=s(this._g)),this._b<1&&(this._b=s(this._b)),this._ok=r.ok,this._tc_id=a++};function n(t,e,r){t=R(t,255),e=R(e,255),r=R(r,255);var a,n=h(t,e,r),o=f(t,e,r),i=(n+o)/2;if(n==o)a=l=0;else{var s=n-o,l=.5<i?s/(2-n-o):s/(n+o);switch(n){case t:a=(e-r)/s+(e<r?6:0);break;case e:a=(r-t)/s+2;break;case r:a=(t-e)/s+4}a/=6}return{h:a,s:l,l:i}}function l(t,e,r){t=R(t,255),e=R(e,255),r=R(r,255);var a,n=h(t,e,r),o=f(t,e,r),i=n,s=n-o,l=0===n?0:s/n;if(n==o)a=0;else{switch(n){case t:a=(e-r)/s+(e<r?6:0);break;case e:a=(r-t)/s+2;break;case r:a=(t-e)/s+4}a/=6}return{h:a,s:l,v:i}}function e(t,e,r,a){var n=[T(s(t).toString(16)),T(s(e).toString(16)),T(s(r).toString(16))];return a&&n[0].charAt(0)==n[0].charAt(1)&&n[1].charAt(0)==n[1].charAt(1)&&n[2].charAt(0)==n[2].charAt(1)?n[0].charAt(0)+n[1].charAt(0)+n[2].charAt(0):n.join("")}function d(t,e,r,a){var n;return[T((n=a,Math.round(255*parseFloat(n)).toString(16))),T(s(t).toString(16)),T(s(e).toString(16)),T(s(r).toString(16))].join("")}function r(t,e){e=0===e?0:e||10;var r=u(t).toHsl();return r.s-=e/100,r.s=H(r.s),u(r)}function p(t,e){e=0===e?0:e||10;var r=u(t).toHsl();return r.s+=e/100,r.s=H(r.s),u(r)}function g(t){return u(t).desaturate(100)}function b(t,e){e=0===e?0:e||10;var r=u(t).toHsl();return r.l+=e/100,r.l=H(r.l),u(r)}function v(t,e){e=0===e?0:e||10;var r=u(t).toRgb();return r.r=h(0,f(255,r.r-s(-e/100*255))),r.g=h(0,f(255,r.g-s(-e/100*255))),r.b=h(0,f(255,r.b-s(-e/100*255))),u(r)}function m(t,e){e=0===e?0:e||10;var r=u(t).toHsl();return r.l-=e/100,r.l=H(r.l),u(r)}function y(t,e){var r=u(t).toHsl(),a=(s(r.h)+e)%360;return r.h=a<0?360+a:a,u(r)}function w(t){var e=u(t).toHsl();return e.h=(e.h+180)%360,u(e)}function _(t){var e=u(t).toHsl(),r=e.h;return[u(t),u({h:(r+120)%360,s:e.s,l:e.l}),u({h:(r+240)%360,s:e.s,l:e.l})]}function x(t){var e=u(t).toHsl(),r=e.h;return[u(t),u({h:(r+90)%360,s:e.s,l:e.l}),u({h:(r+180)%360,s:e.s,l:e.l}),u({h:(r+270)%360,s:e.s,l:e.l})]}function k(t){var e=u(t).toHsl(),r=e.h;return[u(t),u({h:(r+72)%360,s:e.s,l:e.l}),u({h:(r+216)%360,s:e.s,l:e.l})]}function S(t,e,r){e=e||6,r=r||30;var a=u(t).toHsl(),n=360/r,o=[u(t)];for(a.h=(a.h-(n*e>>1)+720)%360;--e;)a.h=(a.h+n)%360,o.push(u(a));return o}function C(t,e){e=e||6;for(var r=u(t).toHsv(),a=r.h,n=r.s,o=r.v,i=[],s=1/e;e--;)i.push(u({h:a,s:n,v:o})),o=(o+s)%1;return i}u.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},setAlpha:function(t){return this._a=M(t),this._roundA=s(1e3*this._a)/1e3,this},toHsv:function(){var t=l(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=l(this._r,this._g,this._b),e=s(360*t.h),r=s(100*t.s),a=s(100*t.v);return 1==this._a?"hsv("+e+", "+r+"%, "+a+"%)":"hsva("+e+", "+r+"%, "+a+"%, "+this._roundA+")"},toHsl:function(){var t=n(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=n(this._r,this._g,this._b),e=s(360*t.h),r=s(100*t.s),a=s(100*t.l);return 1==this._a?"hsl("+e+", "+r+"%, "+a+"%)":"hsla("+e+", "+r+"%, "+a+"%, "+this._roundA+")"},toHex:function(t){return e(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(){return d(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:s(this._r),g:s(this._g),b:s(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+s(this._r)+", "+s(this._g)+", "+s(this._b)+")":"rgba("+s(this._r)+", "+s(this._g)+", "+s(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:s(100*R(this._r,255))+"%",g:s(100*R(this._g,255))+"%",b:s(100*R(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+s(100*R(this._r,255))+"%, "+s(100*R(this._g,255))+"%, "+s(100*R(this._b,255))+"%)":"rgba("+s(100*R(this._r,255))+"%, "+s(100*R(this._g,255))+"%, "+s(100*R(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&A[e(this._r,this._g,this._b,!0)]||!1},toFilter:function(t){var e="#"+d(this._r,this._g,this._b,this._a),r=e,a=this._gradientType?"GradientType = 1, ":"";return t&&(r=u(t).toHex8String()),"progid:DXImageTransform.Microsoft.gradient("+a+"startColorstr="+e+",endColorstr="+r+")"},toString:function(t){var e=!!t;t=t||this._format;var r=!1,a=this._a<1&&0<=this._a;return e||!a||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"name"!==t?("rgb"===t&&(r=this.toRgbString()),"prgb"===t&&(r=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(r=this.toHexString()),"hex3"===t&&(r=this.toHexString(!0)),"hex8"===t&&(r=this.toHex8String()),"name"===t&&(r=this.toName()),"hsl"===t&&(r=this.toHslString()),"hsv"===t&&(r=this.toHsvString()),r||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},_applyModification:function(t,e){var r=t.apply(null,[this].concat([].slice.call(e)));return this._r=r._r,this._g=r._g,this._b=r._b,this.setAlpha(r._a),this},lighten:function(){return this._applyModification(b,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(m,arguments)},desaturate:function(){return this._applyModification(r,arguments)},saturate:function(){return this._applyModification(p,arguments)},greyscale:function(){return this._applyModification(g,arguments)},spin:function(){return this._applyModification(y,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(S,arguments)},complement:function(){return this._applyCombination(w,arguments)},monochromatic:function(){return this._applyCombination(C,arguments)},splitcomplement:function(){return this._applyCombination(k,arguments)},triad:function(){return this._applyCombination(_,arguments)},tetrad:function(){return this._applyCombination(x,arguments)}},u.fromRatio=function(t,e){if("object"==typeof t){var r={};for(var a in t)t.hasOwnProperty(a)&&(r[a]="a"===a?t[a]:O(t[a]));t=r}return u(t,e)},u.equals=function(t,e){return!(!t||!e)&&u(t).toRgbString()==u(e).toRgbString()},u.random=function(){return u.fromRatio({r:t(),g:t(),b:t()})},u.mix=function(t,e,r){r=0===r?0:r||50;var a=u(t).toRgb(),n=u(e).toRgb(),o=r/100,i=2*o-1,s=n.a-a.a,l=i*s==-1?i:(i+s)/(1+i*s),c=1-(l=(l+1)/2),f={r:n.r*l+a.r*c,g:n.g*l+a.g*c,b:n.b*l+a.b*c,a:n.a*o+a.a*(1-o)};return u(f)},u.readability=function(t,e){var r=u(t),a=u(e),n=r.toRgb(),o=a.toRgb(),i=r.getBrightness(),s=a.getBrightness(),l=Math.max(n.r,o.r)-Math.min(n.r,o.r)+Math.max(n.g,o.g)-Math.min(n.g,o.g)+Math.max(n.b,o.b)-Math.min(n.b,o.b);return{brightness:Math.abs(i-s),color:l}},u.isReadable=function(t,e){var r=u.readability(t,e);return 125<r.brightness&&500<r.color},u.mostReadable=function(t,e){for(var r=null,a=0,n=!1,o=0;o<e.length;o++){var i=u.readability(t,e[o]),s=125<i.brightness&&500<i.color,l=i.brightness/125*3+i.color/500;(s&&!n||s&&n&&a<l||!s&&!n&&a<l)&&(n=s,a=l,r=u(e[o]))}return r};var P=u.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},A=u.hexNames=function(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[t[r]]=r);return e}(P);function M(t){return t=parseFloat(t),(isNaN(t)||t<0||1<t)&&(t=1),t}function R(t,e){var r;"string"==typeof(r=t)&&-1!=r.indexOf(".")&&1===parseFloat(r)&&(t="100%");var a,n="string"==typeof(a=t)&&-1!=a.indexOf("%");return t=f(e,h(0,parseFloat(t))),n&&(t=parseInt(t*e,10)/100),c.abs(t-e)<1e-6?1:t%e/parseFloat(e)}function H(t){return f(1,h(0,t))}function F(t){return parseInt(t,16)}function T(t){return 1==t.length?"0"+t:""+t}function O(t){return t<=1&&(t=100*t+"%"),t}var q,N,j,E=(N="[\\s|\\(]+("+(q="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+q+")[,|\\s]+("+q+")\\s*\\)?",j="[\\s|\\(]+("+q+")[,|\\s]+("+q+")[,|\\s]+("+q+")[,|\\s]+("+q+")\\s*\\)?",{rgb:new RegExp("rgb"+N),rgba:new RegExp("rgba"+j),hsl:new RegExp("hsl"+N),hsla:new RegExp("hsla"+j),hsv:new RegExp("hsv"+N),hsva:new RegExp("hsva"+j),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});window.tinycolor=u}(),jt(function(){jt.fn.spectrum.load&&jt.fn.spectrum.processNativeColorInputs()})});
@@ -1,114 +1,136 @@
1
- // Spectrum Colorpicker v1.2.0
1
+ // Spectrum Colorpicker v1.8.1
2
2
  // https://github.com/bgrins/spectrum
3
3
  // Author: Brian Grinstead
4
4
  // License: MIT
5
5
 
6
- (function (window, $, undefined) {
6
+ (function (factory) {
7
+ "use strict";
8
+
9
+ if (typeof define === 'function' && define.amd) { // AMD
10
+ define(['jquery'], factory);
11
+ }
12
+ else if (typeof exports == "object" && typeof module == "object") { // CommonJS
13
+ module.exports = factory(require('jquery'));
14
+ }
15
+ else { // Browser
16
+ factory(jQuery);
17
+ }
18
+ })(function($, undefined) {
19
+ "use strict";
20
+
7
21
  var defaultOpts = {
8
22
 
9
- // Callbacks
10
- beforeShow: noop,
11
- move: noop,
12
- change: noop,
13
- show: noop,
14
- hide: noop,
15
-
16
- // Options
17
- color: false,
18
- flat: false,
19
- showInput: false,
20
- allowEmpty: false,
21
- showButtons: true,
22
- clickoutFiresChange: false,
23
- showInitial: false,
24
- showPalette: false,
25
- showPaletteOnly: false,
26
- showSelectionPalette: true,
27
- localStorageKey: false,
28
- appendTo: "body",
29
- maxSelectionSize: 7,
30
- cancelText: "cancel",
31
- chooseText: "choose",
32
- preferredFormat: false,
33
- className: "",
34
- showAlpha: false,
35
- theme: "sp-light",
36
- palette: ['fff', '000'],
37
- selectionPalette: [],
38
- disabled: false
39
- },
40
- spectrums = [],
41
- IE = !!/msie/i.exec( window.navigator.userAgent ),
42
- rgbaSupport = (function() {
43
- function contains( str, substr ) {
44
- return !!~('' + str).indexOf(substr);
45
- }
46
-
47
- var elem = document.createElement('div');
48
- var style = elem.style;
49
- style.cssText = 'background-color:rgba(0,0,0,.5)';
50
- return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
51
- })(),
52
- inputTypeColorSupport = (function() {
53
- var colorInput = $("<input type='color' value='!' />")[0];
54
- return colorInput.type === "color" && colorInput.value !== "!";
55
- })(),
56
- replaceInput = [
57
- "<div class='sp-replacer'>",
23
+ // Callbacks
24
+ beforeShow: noop,
25
+ move: noop,
26
+ change: noop,
27
+ show: noop,
28
+ hide: noop,
29
+
30
+ // Options
31
+ color: false,
32
+ flat: false,
33
+ showInput: false,
34
+ allowEmpty: false,
35
+ showButtons: true,
36
+ clickoutFiresChange: true,
37
+ showInitial: false,
38
+ showPalette: false,
39
+ showPaletteOnly: false,
40
+ hideAfterPaletteSelect: false,
41
+ togglePaletteOnly: false,
42
+ showSelectionPalette: true,
43
+ localStorageKey: false,
44
+ appendTo: "body",
45
+ maxSelectionSize: 7,
46
+ cancelText: "cancel",
47
+ chooseText: "choose",
48
+ togglePaletteMoreText: "more",
49
+ togglePaletteLessText: "less",
50
+ clearText: "Clear Color Selection",
51
+ noColorSelectedText: "No Color Selected",
52
+ preferredFormat: false,
53
+ className: "", // Deprecated - use containerClassName and replacerClassName instead.
54
+ containerClassName: "",
55
+ replacerClassName: "",
56
+ showAlpha: false,
57
+ theme: "sp-light",
58
+ palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]],
59
+ selectionPalette: [],
60
+ disabled: false,
61
+ offset: null
62
+ },
63
+ spectrums = [],
64
+ IE = !!/msie/i.exec( window.navigator.userAgent ),
65
+ rgbaSupport = (function() {
66
+ function contains( str, substr ) {
67
+ return !!~('' + str).indexOf(substr);
68
+ }
69
+
70
+ var elem = document.createElement('div');
71
+ var style = elem.style;
72
+ style.cssText = 'background-color:rgba(0,0,0,.5)';
73
+ return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
74
+ })(),
75
+ replaceInput = [
76
+ "<div class='sp-replacer'>",
58
77
  "<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
59
78
  "<div class='sp-dd'>&#9660;</div>",
60
- "</div>"
61
- ].join(''),
62
- markup = (function () {
79
+ "</div>"
80
+ ].join(''),
81
+ markup = (function () {
63
82
 
64
- // IE does not support gradients with multiple stops, so we need to simulate
65
- // that for the rainbow slider with 8 divs that each have a single gradient
66
- var gradientFix = "";
67
- if (IE) {
68
- for (var i = 1; i <= 6; i++) {
69
- gradientFix += "<div class='sp-" + i + "'></div>";
70
- }
83
+ // IE does not support gradients with multiple stops, so we need to simulate
84
+ // that for the rainbow slider with 8 divs that each have a single gradient
85
+ var gradientFix = "";
86
+ if (IE) {
87
+ for (var i = 1; i <= 6; i++) {
88
+ gradientFix += "<div class='sp-" + i + "'></div>";
71
89
  }
90
+ }
72
91
 
73
- return [
74
- "<div class='sp-container sp-hidden'>",
92
+ return [
93
+ "<div class='sp-container sp-hidden'>",
75
94
  "<div class='sp-palette-container'>",
76
- "<div class='sp-palette sp-thumb sp-cf'></div>",
95
+ "<div class='sp-palette sp-thumb sp-cf'></div>",
96
+ "<div class='sp-palette-button-container sp-cf'>",
97
+ "<button type='button' class='sp-palette-toggle'></button>",
98
+ "</div>",
77
99
  "</div>",
78
100
  "<div class='sp-picker-container'>",
79
- "<div class='sp-top sp-cf'>",
80
- "<div class='sp-fill'></div>",
81
- "<div class='sp-top-inner'>",
82
- "<div class='sp-color'>",
83
- "<div class='sp-sat'>",
84
- "<div class='sp-val'>",
85
- "<div class='sp-dragger'></div>",
86
- "</div>",
101
+ "<div class='sp-top sp-cf'>",
102
+ "<div class='sp-fill'></div>",
103
+ "<div class='sp-top-inner'>",
104
+ "<div class='sp-color'>",
105
+ "<div class='sp-sat'>",
106
+ "<div class='sp-val'>",
107
+ "<div class='sp-dragger'></div>",
108
+ "</div>",
109
+ "</div>",
110
+ "</div>",
111
+ "<div class='sp-clear sp-clear-display'>",
112
+ "</div>",
113
+ "<div class='sp-hue'>",
114
+ "<div class='sp-slider'></div>",
115
+ gradientFix,
116
+ "</div>",
117
+ "</div>",
118
+ "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
119
+ "</div>",
120
+ "<div class='sp-input-container sp-cf'>",
121
+ "<input class='sp-input' type='text' spellcheck='false' />",
122
+ "</div>",
123
+ "<div class='sp-initial sp-thumb sp-cf'></div>",
124
+ "<div class='sp-button-container sp-cf'>",
125
+ "<a class='sp-cancel' href='#'></a>",
126
+ "<button type='button' class='sp-choose'></button>",
127
+ "</div>",
87
128
  "</div>",
88
- "</div>",
89
- "<div class='sp-clear sp-clear-display' title='Clear Color Selection'>",
90
- "</div>",
91
- "<div class='sp-hue'>",
92
- "<div class='sp-slider'></div>",
93
- gradientFix,
94
- "</div>",
95
- "</div>",
96
- "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
97
- "</div>",
98
- "<div class='sp-input-container sp-cf'>",
99
- "<input class='sp-input' type='text' spellcheck='false' />",
100
- "</div>",
101
- "<div class='sp-initial sp-thumb sp-cf'></div>",
102
- "<div class='sp-button-container sp-cf'>",
103
- "<a class='sp-cancel' href='#'></a>",
104
- "<button class='sp-choose'></button>",
105
- "</div>",
106
- "</div>",
107
- "</div>"
108
- ].join("");
109
- })();
129
+ "</div>"
130
+ ].join("");
131
+ })();
110
132
 
111
- function paletteTemplate (p, color, className) {
133
+ function paletteTemplate (p, color, className, opts) {
112
134
  var html = [];
113
135
  for (var i = 0; i < p.length; i++) {
114
136
  var current = p[i];
@@ -116,12 +138,17 @@
116
138
  var tiny = tinycolor(current);
117
139
  var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
118
140
  c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
119
-
141
+ var formattedString = tiny.toString(opts.preferredFormat || "rgb");
120
142
  var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
121
- html.push('<span title="' + tiny.toRgbString() + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
143
+ html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';"></span></span>');
122
144
  } else {
123
145
  var cls = 'sp-clear-display';
124
- html.push('<span title="No Color Selected" data-color="" style="background-color:transparent;" class="' + cls + '"></span>');
146
+ html.push($('<div />')
147
+ .append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>')
148
+ .attr('title', opts.noColorSelectedText)
149
+ )
150
+ .html()
151
+ );
125
152
  }
126
153
  }
127
154
  return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
@@ -158,6 +185,7 @@
158
185
  callbacks = opts.callbacks,
159
186
  resize = throttle(reflow, 10),
160
187
  visible = false,
188
+ isDragging = false,
161
189
  dragWidth = 0,
162
190
  dragHeight = 0,
163
191
  dragHelperHeight = 0,
@@ -170,8 +198,9 @@
170
198
  currentSaturation = 0,
171
199
  currentValue = 0,
172
200
  currentAlpha = 1,
173
- palette = opts.palette.slice(0),
174
- paletteArray = $.isArray(palette[0]) ? palette : [palette],
201
+ palette = [],
202
+ paletteArray = [],
203
+ paletteLookup = {},
175
204
  selectionPalette = opts.selectionPalette.slice(0),
176
205
  maxSelectionSize = opts.maxSelectionSize,
177
206
  draggingClass = "sp-dragging",
@@ -182,6 +211,7 @@
182
211
  boundElement = $(element),
183
212
  disabled = false,
184
213
  container = $(markup, doc).addClass(theme),
214
+ pickerContainer = container.find(".sp-picker-container"),
185
215
  dragger = container.find(".sp-color"),
186
216
  dragHelper = container.find(".sp-dragger"),
187
217
  slider = container.find(".sp-hue"),
@@ -195,16 +225,16 @@
195
225
  cancelButton = container.find(".sp-cancel"),
196
226
  clearButton = container.find(".sp-clear"),
197
227
  chooseButton = container.find(".sp-choose"),
228
+ toggleButton = container.find(".sp-palette-toggle"),
198
229
  isInput = boundElement.is("input"),
199
- isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr("type") === "color",
230
+ isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
200
231
  shouldReplace = isInput && !flat,
201
- replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]),
232
+ replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
202
233
  offsetElement = (shouldReplace) ? replacer : boundElement,
203
234
  previewElement = replacer.find(".sp-preview-inner"),
204
235
  initialColor = opts.color || (isInput && boundElement.val()),
205
236
  colorOnShow = false,
206
- preferredFormat = opts.preferredFormat,
207
- currentPreferredFormat = preferredFormat,
237
+ currentPreferredFormat = opts.preferredFormat,
208
238
  clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
209
239
  isEmpty = !initialColor,
210
240
  allowEmpty = opts.allowEmpty && !isInputTypeColor;
@@ -215,15 +245,30 @@
215
245
  opts.showPalette = true;
216
246
  }
217
247
 
248
+ toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
249
+
250
+ if (opts.palette) {
251
+ palette = opts.palette.slice(0);
252
+ paletteArray = $.isArray(palette[0]) ? palette : [palette];
253
+ paletteLookup = {};
254
+ for (var i = 0; i < paletteArray.length; i++) {
255
+ for (var j = 0; j < paletteArray[i].length; j++) {
256
+ var rgb = tinycolor(paletteArray[i][j]).toRgbString();
257
+ paletteLookup[rgb] = true;
258
+ }
259
+ }
260
+ }
261
+
218
262
  container.toggleClass("sp-flat", flat);
219
263
  container.toggleClass("sp-input-disabled", !opts.showInput);
220
264
  container.toggleClass("sp-alpha-enabled", opts.showAlpha);
221
265
  container.toggleClass("sp-clear-enabled", allowEmpty);
222
266
  container.toggleClass("sp-buttons-disabled", !opts.showButtons);
267
+ container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
223
268
  container.toggleClass("sp-palette-disabled", !opts.showPalette);
224
269
  container.toggleClass("sp-palette-only", opts.showPaletteOnly);
225
270
  container.toggleClass("sp-initial-disabled", !opts.showInitial);
226
- container.addClass(opts.className);
271
+ container.addClass(opts.className).addClass(opts.containerClassName);
227
272
 
228
273
  reflow();
229
274
  }
@@ -257,27 +302,9 @@
257
302
  appendTo.append(container);
258
303
  }
259
304
 
260
- if (localStorageKey && window.localStorage) {
261
-
262
- // Migrate old palettes over to new format. May want to remove this eventually.
263
- try {
264
- var oldPalette = window.localStorage[localStorageKey].split(",#");
265
- if (oldPalette.length > 1) {
266
- delete window.localStorage[localStorageKey];
267
- $.each(oldPalette, function(i, c) {
268
- addColorToSelectionPalette(c);
269
- });
270
- }
271
- }
272
- catch(e) { }
273
-
274
- try {
275
- selectionPalette = window.localStorage[localStorageKey].split(";");
276
- }
277
- catch (e) { }
278
- }
305
+ updateSelectionPaletteFromStorage();
279
306
 
280
- offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
307
+ offsetElement.on("click.spectrum touchstart.spectrum", function (e) {
281
308
  if (!disabled) {
282
309
  toggle();
283
310
  }
@@ -298,44 +325,65 @@
298
325
 
299
326
  // Handle user typed input
300
327
  textInput.change(setFromTextInput);
301
- textInput.bind("paste", function () {
328
+ textInput.on("paste", function () {
302
329
  setTimeout(setFromTextInput, 1);
303
330
  });
304
331
  textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
305
332
 
306
333
  cancelButton.text(opts.cancelText);
307
- cancelButton.bind("click.spectrum", function (e) {
334
+ cancelButton.on("click.spectrum", function (e) {
308
335
  e.stopPropagation();
309
336
  e.preventDefault();
310
- hide("cancel");
337
+ revert();
338
+ hide();
311
339
  });
312
340
 
313
-
314
- clearButton.bind("click.spectrum", function (e) {
341
+ clearButton.attr("title", opts.clearText);
342
+ clearButton.on("click.spectrum", function (e) {
315
343
  e.stopPropagation();
316
344
  e.preventDefault();
317
-
318
345
  isEmpty = true;
319
-
320
346
  move();
347
+
321
348
  if(flat) {
322
349
  //for the flat style, this is a change event
323
350
  updateOriginalInput(true);
324
351
  }
325
352
  });
326
353
 
327
-
328
354
  chooseButton.text(opts.chooseText);
329
- chooseButton.bind("click.spectrum", function (e) {
355
+ chooseButton.on("click.spectrum", function (e) {
330
356
  e.stopPropagation();
331
357
  e.preventDefault();
332
358
 
359
+ if (IE && textInput.is(":focus")) {
360
+ textInput.trigger('change');
361
+ }
362
+
333
363
  if (isValid()) {
334
364
  updateOriginalInput(true);
335
365
  hide();
336
366
  }
337
367
  });
338
368
 
369
+ toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
370
+ toggleButton.on("click.spectrum", function (e) {
371
+ e.stopPropagation();
372
+ e.preventDefault();
373
+
374
+ opts.showPaletteOnly = !opts.showPaletteOnly;
375
+
376
+ // To make sure the Picker area is drawn on the right, next to the
377
+ // Palette area (and not below the palette), first move the Palette
378
+ // to the left to make space for the picker, plus 5px extra.
379
+ // The 'applyOptions' function puts the whole container back into place
380
+ // and takes care of the button-text and the sp-palette-only CSS class.
381
+ if (!opts.showPaletteOnly && !flat) {
382
+ container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
383
+ }
384
+ applyOptions();
385
+ });
386
+
339
387
  draggable(alphaSlider, function (dragX, dragY, e) {
340
388
  currentAlpha = (dragX / alphaWidth);
341
389
  isEmpty = false;
@@ -344,11 +392,14 @@
344
392
  }
345
393
 
346
394
  move();
347
- });
395
+ }, dragStart, dragStop);
348
396
 
349
397
  draggable(slider, function (dragX, dragY) {
350
398
  currentHue = parseFloat(dragY / slideHeight);
351
399
  isEmpty = false;
400
+ if (!opts.showAlpha) {
401
+ currentAlpha = 1;
402
+ }
352
403
  move();
353
404
  }, dragStart, dragStop);
354
405
 
@@ -377,6 +428,9 @@
377
428
  }
378
429
 
379
430
  isEmpty = false;
431
+ if (!opts.showAlpha) {
432
+ currentAlpha = 1;
433
+ }
380
434
 
381
435
  move();
382
436
 
@@ -388,7 +442,7 @@
388
442
  // In case color was black - update the preview UI and set the format
389
443
  // since the set function will not run (default color is black).
390
444
  updateUI();
391
- currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;
445
+ currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;
392
446
 
393
447
  addColorToSelectionPalette(initialColor);
394
448
  }
@@ -400,31 +454,61 @@
400
454
  show();
401
455
  }
402
456
 
403
- function palletElementClick(e) {
457
+ function paletteElementClick(e) {
404
458
  if (e.data && e.data.ignore) {
405
- set($(this).data("color"));
459
+ set($(e.target).closest(".sp-thumb-el").data("color"));
406
460
  move();
407
461
  }
408
462
  else {
409
- set($(this).data("color"));
410
- updateOriginalInput(true);
463
+ set($(e.target).closest(".sp-thumb-el").data("color"));
411
464
  move();
412
- hide();
465
+
466
+ // If the picker is going to close immediately, a palette selection
467
+ // is a change. Otherwise, it's a move only.
468
+ if (opts.hideAfterPaletteSelect) {
469
+ updateOriginalInput(true);
470
+ hide();
471
+ } else {
472
+ updateOriginalInput();
473
+ }
413
474
  }
414
475
 
415
476
  return false;
416
477
  }
417
478
 
418
479
  var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
419
- paletteContainer.delegate(".sp-thumb-el", paletteEvent, palletElementClick);
420
- initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, palletElementClick);
480
+ paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
481
+ initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, paletteElementClick);
482
+ }
483
+
484
+ function updateSelectionPaletteFromStorage() {
485
+
486
+ if (localStorageKey && window.localStorage) {
487
+
488
+ // Migrate old palettes over to new format. May want to remove this eventually.
489
+ try {
490
+ var oldPalette = window.localStorage[localStorageKey].split(",#");
491
+ if (oldPalette.length > 1) {
492
+ delete window.localStorage[localStorageKey];
493
+ $.each(oldPalette, function(i, c) {
494
+ addColorToSelectionPalette(c);
495
+ });
496
+ }
497
+ }
498
+ catch(e) { }
499
+
500
+ try {
501
+ selectionPalette = window.localStorage[localStorageKey].split(";");
502
+ }
503
+ catch (e) { }
504
+ }
421
505
  }
422
506
 
423
507
  function addColorToSelectionPalette(color) {
424
508
  if (showSelectionPalette) {
425
- var colorRgb = tinycolor(color).toRgbString();
426
- if ($.inArray(colorRgb, selectionPalette) === -1) {
427
- selectionPalette.push(colorRgb);
509
+ var rgb = tinycolor(color).toRgbString();
510
+ if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
511
+ selectionPalette.push(rgb);
428
512
  while(selectionPalette.length > maxSelectionSize) {
429
513
  selectionPalette.shift();
430
514
  }
@@ -441,25 +525,12 @@
441
525
 
442
526
  function getUniqueSelectionPalette() {
443
527
  var unique = [];
444
- var p = selectionPalette;
445
- var paletteLookup = {};
446
- var rgb;
447
-
448
528
  if (opts.showPalette) {
529
+ for (var i = 0; i < selectionPalette.length; i++) {
530
+ var rgb = tinycolor(selectionPalette[i]).toRgbString();
449
531
 
450
- for (var i = 0; i < paletteArray.length; i++) {
451
- for (var j = 0; j < paletteArray[i].length; j++) {
452
- rgb = tinycolor(paletteArray[i][j]).toRgbString();
453
- paletteLookup[rgb] = true;
454
- }
455
- }
456
-
457
- for (i = 0; i < p.length; i++) {
458
- rgb = tinycolor(p[i]).toRgbString();
459
-
460
- if (!paletteLookup.hasOwnProperty(rgb)) {
461
- unique.push(p[i]);
462
- paletteLookup[rgb] = true;
532
+ if (!paletteLookup[rgb]) {
533
+ unique.push(selectionPalette[i]);
463
534
  }
464
535
  }
465
536
  }
@@ -472,11 +543,13 @@
472
543
  var currentColor = get();
473
544
 
474
545
  var html = $.map(paletteArray, function (palette, i) {
475
- return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i);
546
+ return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
476
547
  });
477
548
 
549
+ updateSelectionPaletteFromStorage();
550
+
478
551
  if (selectionPalette) {
479
- html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection"));
552
+ html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
480
553
  }
481
554
 
482
555
  paletteContainer.html(html.join(""));
@@ -486,7 +559,7 @@
486
559
  if (opts.showInitial) {
487
560
  var initial = colorOnShow;
488
561
  var current = get();
489
- initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial"));
562
+ initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
490
563
  }
491
564
  }
492
565
 
@@ -494,12 +567,16 @@
494
567
  if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
495
568
  reflow();
496
569
  }
570
+ isDragging = true;
497
571
  container.addClass(draggingClass);
498
572
  shiftMovementDirection = null;
573
+ boundElement.trigger('dragstart.spectrum', [ get() ]);
499
574
  }
500
575
 
501
576
  function dragStop() {
577
+ isDragging = false;
502
578
  container.removeClass(draggingClass);
579
+ boundElement.trigger('dragstop.spectrum', [ get() ]);
503
580
  }
504
581
 
505
582
  function setFromTextInput() {
@@ -508,11 +585,15 @@
508
585
 
509
586
  if ((value === null || value === "") && allowEmpty) {
510
587
  set(null);
588
+ move();
589
+ updateOriginalInput();
511
590
  }
512
591
  else {
513
592
  var tiny = tinycolor(value);
514
- if (tiny.ok) {
593
+ if (tiny.isValid()) {
515
594
  set(tiny);
595
+ move();
596
+ updateOriginalInput();
516
597
  }
517
598
  else {
518
599
  textInput.addClass("sp-validation-error");
@@ -546,14 +627,12 @@
546
627
  hideAll();
547
628
  visible = true;
548
629
 
549
- $(doc).bind("click.spectrum", hide);
550
- $(window).bind("resize.spectrum", resize);
630
+ $(doc).on("keydown.spectrum", onkeydown);
631
+ $(doc).on("click.spectrum", clickout);
632
+ $(window).on("resize.spectrum", resize);
551
633
  replacer.addClass("sp-active");
552
634
  container.removeClass("sp-hidden");
553
635
 
554
- if (opts.showPalette) {
555
- drawPalette();
556
- }
557
636
  reflow();
558
637
  updateUI();
559
638
 
@@ -564,52 +643,66 @@
564
643
  boundElement.trigger('show.spectrum', [ colorOnShow ]);
565
644
  }
566
645
 
567
- function hide(e) {
646
+ function onkeydown(e) {
647
+ // Close on ESC
648
+ if (e.keyCode === 27) {
649
+ hide();
650
+ }
651
+ }
652
+
653
+ function clickout(e) {
654
+ // Return on right click.
655
+ if (e.button == 2) { return; }
656
+
657
+ // If a drag event was happening during the mouseup, don't hide
658
+ // on click.
659
+ if (isDragging) { return; }
568
660
 
569
- // Return on right click
570
- if (e && e.type == "click" && e.button == 2) { return; }
661
+ if (clickoutFiresChange) {
662
+ updateOriginalInput(true);
663
+ }
664
+ else {
665
+ revert();
666
+ }
667
+ hide();
668
+ }
571
669
 
670
+ function hide() {
572
671
  // Return if hiding is unnecessary
573
672
  if (!visible || flat) { return; }
574
673
  visible = false;
575
674
 
576
- $(doc).unbind("click.spectrum", hide);
577
- $(window).unbind("resize.spectrum", resize);
675
+ $(doc).off("keydown.spectrum", onkeydown);
676
+ $(doc).off("click.spectrum", clickout);
677
+ $(window).off("resize.spectrum", resize);
578
678
 
579
679
  replacer.removeClass("sp-active");
580
680
  container.addClass("sp-hidden");
581
681
 
582
- var colorHasChanged = !tinycolor.equals(get(), colorOnShow);
583
-
584
- if (colorHasChanged) {
585
- if (clickoutFiresChange && e !== "cancel") {
586
- updateOriginalInput(true);
587
- }
588
- else {
589
- revert();
590
- }
591
- }
592
-
593
682
  callbacks.hide(get());
594
683
  boundElement.trigger('hide.spectrum', [ get() ]);
595
684
  }
596
685
 
597
686
  function revert() {
598
687
  set(colorOnShow, true);
688
+ updateOriginalInput(true);
599
689
  }
600
690
 
601
691
  function set(color, ignoreFormatChange) {
602
692
  if (tinycolor.equals(color, get())) {
693
+ // Update UI just in case a validation error needs
694
+ // to be cleared.
695
+ updateUI();
603
696
  return;
604
697
  }
605
698
 
606
- var newColor;
699
+ var newColor, newHsv;
607
700
  if (!color && allowEmpty) {
608
701
  isEmpty = true;
609
702
  } else {
610
703
  isEmpty = false;
611
704
  newColor = tinycolor(color);
612
- var newHsv = newColor.toHsv();
705
+ newHsv = newColor.toHsv();
613
706
 
614
707
  currentHue = (newHsv.h % 360) / 360;
615
708
  currentSaturation = newHsv.s;
@@ -618,8 +711,8 @@
618
711
  }
619
712
  updateUI();
620
713
 
621
- if (newColor && newColor.ok && !ignoreFormatChange) {
622
- currentPreferredFormat = preferredFormat || newColor.format;
714
+ if (newColor && newColor.isValid() && !ignoreFormatChange) {
715
+ currentPreferredFormat = opts.preferredFormat || newColor.getFormat();
623
716
  }
624
717
  }
625
718
 
@@ -634,7 +727,7 @@
634
727
  h: currentHue,
635
728
  s: currentSaturation,
636
729
  v: currentValue,
637
- a: Math.round(currentAlpha * 100) / 100
730
+ a: Math.round(currentAlpha * 1000) / 1000
638
731
  }, { format: opts.format || currentPreferredFormat });
639
732
  }
640
733
 
@@ -661,7 +754,7 @@
661
754
 
662
755
  // Get a format that alpha will be included in (hex and names ignore alpha)
663
756
  var format = currentPreferredFormat;
664
- if (currentAlpha < 1) {
757
+ if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
665
758
  if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
666
759
  format = "rgb";
667
760
  }
@@ -670,7 +763,7 @@
670
763
  var realColor = get({ format: format }),
671
764
  displayColor = '';
672
765
 
673
- //reset background info for preview element
766
+ //reset background info for preview element
674
767
  previewElement.removeClass("sp-clear-display");
675
768
  previewElement.css('background-color', 'transparent');
676
769
 
@@ -704,12 +797,15 @@
704
797
  alphaSliderInner.css("background", "-webkit-" + gradient);
705
798
  alphaSliderInner.css("background", "-moz-" + gradient);
706
799
  alphaSliderInner.css("background", "-ms-" + gradient);
707
- alphaSliderInner.css("background", gradient);
800
+ // Use current syntax gradient on unprefixed property.
801
+ alphaSliderInner.css("background",
802
+ "linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
708
803
  }
709
804
  }
710
805
 
711
806
  displayColor = realColor.toString(format);
712
807
  }
808
+
713
809
  // Update the text entry input as it changes happen
714
810
  if (opts.showInput) {
715
811
  textInput.val(displayColor);
@@ -750,19 +846,19 @@
750
846
  Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
751
847
  );
752
848
  dragHelper.css({
753
- "top": dragY,
754
- "left": dragX
849
+ "top": dragY + "px",
850
+ "left": dragX + "px"
755
851
  });
756
852
 
757
853
  var alphaX = currentAlpha * alphaWidth;
758
854
  alphaSlideHelper.css({
759
- "left": alphaX - (alphaSlideHelperWidth / 2)
855
+ "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
760
856
  });
761
857
 
762
858
  // Where to show the bar that displays your current selected hue
763
859
  var slideY = (currentHue) * slideHeight;
764
860
  slideHelper.css({
765
- "top": slideY - slideHelperHeight
861
+ "top": (slideY - slideHelperHeight) + "px"
766
862
  });
767
863
  }
768
864
  }
@@ -772,7 +868,7 @@
772
868
  displayColor = '',
773
869
  hasChanged = !tinycolor.equals(color, colorOnShow);
774
870
 
775
- if(color) {
871
+ if (color) {
776
872
  displayColor = color.toString(currentPreferredFormat);
777
873
  // Update the selection palette with the current color
778
874
  addColorToSelectionPalette(color);
@@ -782,8 +878,6 @@
782
878
  boundElement.val(displayColor);
783
879
  }
784
880
 
785
- colorOnShow = color;
786
-
787
881
  if (fireCallback && hasChanged) {
788
882
  callbacks.change(color);
789
883
  boundElement.trigger('change', [ color ]);
@@ -791,6 +885,9 @@
791
885
  }
792
886
 
793
887
  function reflow() {
888
+ if (!visible) {
889
+ return; // Calculations would be useless and wouldn't be reliable anyways
890
+ }
794
891
  dragWidth = dragger.width();
795
892
  dragHeight = dragger.height();
796
893
  dragHelperHeight = dragHelper.height();
@@ -802,15 +899,25 @@
802
899
 
803
900
  if (!flat) {
804
901
  container.css("position", "absolute");
805
- container.offset(getOffset(container, offsetElement));
902
+ if (opts.offset) {
903
+ container.offset(opts.offset);
904
+ } else {
905
+ container.offset(getOffset(container, offsetElement));
906
+ }
806
907
  }
807
908
 
808
909
  updateHelperLocations();
910
+
911
+ if (opts.showPalette) {
912
+ drawPalette();
913
+ }
914
+
915
+ boundElement.trigger('reflow.spectrum');
809
916
  }
810
917
 
811
918
  function destroy() {
812
919
  boundElement.show();
813
- offsetElement.unbind("click.spectrum touchstart.spectrum");
920
+ offsetElement.off("click.spectrum touchstart.spectrum");
814
921
  container.remove();
815
922
  replacer.remove();
816
923
  spectrums[spect.id] = null;
@@ -825,6 +932,10 @@
825
932
  }
826
933
 
827
934
  opts[optionName] = optionValue;
935
+
936
+ if (optionName === "preferredFormat") {
937
+ currentPreferredFormat = opts.preferredFormat;
938
+ }
828
939
  applyOptions();
829
940
  }
830
941
 
@@ -841,6 +952,11 @@
841
952
  offsetElement.addClass("sp-disabled");
842
953
  }
843
954
 
955
+ function setOffset(coord) {
956
+ opts.offset = coord;
957
+ reflow();
958
+ }
959
+
844
960
  initialize();
845
961
 
846
962
  var spect = {
@@ -851,6 +967,7 @@
851
967
  option: option,
852
968
  enable: enable,
853
969
  disable: disable,
970
+ offset: setOffset,
854
971
  set: function (c) {
855
972
  set(c);
856
973
  updateOriginalInput();
@@ -866,9 +983,9 @@
866
983
  }
867
984
 
868
985
  /**
869
- * checkOffset - get the offset below/above and left/right element depending on screen position
870
- * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
871
- */
986
+ * checkOffset - get the offset below/above and left/right element depending on screen position
987
+ * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
988
+ */
872
989
  function getOffset(picker, input) {
873
990
  var extraY = 0;
874
991
  var dpWidth = picker.outerWidth();
@@ -879,37 +996,47 @@
879
996
  var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
880
997
  var viewHeight = docElem.clientHeight + $(doc).scrollTop();
881
998
  var offset = input.offset();
882
- offset.top += inputHeight;
883
-
884
- offset.left -=
885
- Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
886
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
887
-
888
- offset.top -=
889
- Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
890
- Math.abs(dpHeight + inputHeight - extraY) : extraY));
891
-
892
- return offset;
999
+ var offsetLeft = offset.left;
1000
+ var offsetTop = offset.top;
1001
+
1002
+ offsetTop += inputHeight;
1003
+
1004
+ offsetLeft -=
1005
+ Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
1006
+ Math.abs(offsetLeft + dpWidth - viewWidth) : 0);
1007
+
1008
+ offsetTop -=
1009
+ Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
1010
+ Math.abs(dpHeight + inputHeight - extraY) : extraY));
1011
+
1012
+ return {
1013
+ top: offsetTop,
1014
+ bottom: offset.bottom,
1015
+ left: offsetLeft,
1016
+ right: offset.right,
1017
+ width: offset.width,
1018
+ height: offset.height
1019
+ };
893
1020
  }
894
1021
 
895
1022
  /**
896
- * noop - do nothing
897
- */
1023
+ * noop - do nothing
1024
+ */
898
1025
  function noop() {
899
1026
 
900
1027
  }
901
1028
 
902
1029
  /**
903
- * stopPropagation - makes the code only doing this a little easier to read in line
904
- */
1030
+ * stopPropagation - makes the code only doing this a little easier to read in line
1031
+ */
905
1032
  function stopPropagation(e) {
906
1033
  e.stopPropagation();
907
1034
  }
908
1035
 
909
1036
  /**
910
- * Create a function bound to a given object
911
- * Thanks to underscore.js
912
- */
1037
+ * Create a function bound to a given object
1038
+ * Thanks to underscore.js
1039
+ */
913
1040
  function bind(func, obj) {
914
1041
  var slice = Array.prototype.slice;
915
1042
  var args = slice.call(arguments, 2);
@@ -919,14 +1046,14 @@
919
1046
  }
920
1047
 
921
1048
  /**
922
- * Lightweight drag helper. Handles containment within the element, so that
923
- * when dragging, the x is within [0,element.width] and y is within [0,element.height]
924
- */
1049
+ * Lightweight drag helper. Handles containment within the element, so that
1050
+ * when dragging, the x is within [0,element.width] and y is within [0,element.height]
1051
+ */
925
1052
  function draggable(element, onmove, onstart, onstop) {
926
1053
  onmove = onmove || function () { };
927
1054
  onstart = onstart || function () { };
928
1055
  onstop = onstop || function () { };
929
- var doc = element.ownerDocument || document;
1056
+ var doc = document;
930
1057
  var dragging = false;
931
1058
  var offset = {};
932
1059
  var maxHeight = 0;
@@ -952,13 +1079,13 @@
952
1079
  function move(e) {
953
1080
  if (dragging) {
954
1081
  // Mouseup happened outside of window
955
- if (IE && document.documentMode < 9 && !e.button) {
1082
+ if (IE && doc.documentMode < 9 && !e.button) {
956
1083
  return stop();
957
1084
  }
958
1085
 
959
- var touches = e.originalEvent.touches;
960
- var pageX = touches ? touches[0].pageX : e.pageX;
961
- var pageY = touches ? touches[0].pageY : e.pageY;
1086
+ var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
1087
+ var pageX = t0 && t0.pageX || e.pageX;
1088
+ var pageY = t0 && t0.pageY || e.pageY;
962
1089
 
963
1090
  var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
964
1091
  var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
@@ -971,9 +1098,9 @@
971
1098
  onmove.apply(element, [dragX, dragY, e]);
972
1099
  }
973
1100
  }
1101
+
974
1102
  function start(e) {
975
1103
  var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
976
- var touches = e.originalEvent.touches;
977
1104
 
978
1105
  if (!rightclick && !dragging) {
979
1106
  if (onstart.apply(element, arguments) !== false) {
@@ -982,27 +1109,31 @@
982
1109
  maxWidth = $(element).width();
983
1110
  offset = $(element).offset();
984
1111
 
985
- $(doc).bind(duringDragEvents);
1112
+ $(doc).on(duringDragEvents);
986
1113
  $(doc.body).addClass("sp-dragging");
987
1114
 
988
- if (!hasTouch) {
989
- move(e);
990
- }
1115
+ move(e);
991
1116
 
992
1117
  prevent(e);
993
1118
  }
994
1119
  }
995
1120
  }
1121
+
996
1122
  function stop() {
997
1123
  if (dragging) {
998
- $(doc).unbind(duringDragEvents);
1124
+ $(doc).off(duringDragEvents);
999
1125
  $(doc.body).removeClass("sp-dragging");
1000
- onstop.apply(element, arguments);
1126
+
1127
+ // Wait a tick before notifying observers to allow the click event
1128
+ // to fire in Chrome.
1129
+ setTimeout(function() {
1130
+ onstop.apply(element, arguments);
1131
+ }, 0);
1001
1132
  }
1002
1133
  dragging = false;
1003
1134
  }
1004
1135
 
1005
- $(element).bind("touchstart mousedown", start);
1136
+ $(element).on("touchstart mousedown", start);
1006
1137
  }
1007
1138
 
1008
1139
  function throttle(func, wait, debounce) {
@@ -1018,12 +1149,13 @@
1018
1149
  };
1019
1150
  }
1020
1151
 
1021
-
1022
- function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}
1152
+ function inputTypeColorSupport() {
1153
+ return $.fn.spectrum.inputTypeColorSupport();
1154
+ }
1023
1155
 
1024
1156
  /**
1025
- * Define a jQuery plugin
1026
- */
1157
+ * Define a jQuery plugin
1158
+ */
1027
1159
  var dataID = "spectrum.id";
1028
1160
  $.fn.spectrum = function (opts, extra) {
1029
1161
 
@@ -1035,7 +1167,6 @@
1035
1167
  this.each(function () {
1036
1168
  var spect = spectrums[$(this).data(dataID)];
1037
1169
  if (spect) {
1038
-
1039
1170
  var method = spect[opts];
1040
1171
  if (!method) {
1041
1172
  throw new Error( "Spectrum: no such method: '" + opts + "'" );
@@ -1065,7 +1196,8 @@
1065
1196
 
1066
1197
  // Initializing a new instance of spectrum
1067
1198
  return this.spectrum("destroy").each(function () {
1068
- var spect = spectrum(this, opts);
1199
+ var options = $.extend({}, $(this).data(), opts);
1200
+ var spect = spectrum(this, options);
1069
1201
  $(this).data(dataID, spect.id);
1070
1202
  });
1071
1203
  };
@@ -1074,937 +1206,1136 @@
1074
1206
  $.fn.spectrum.loadOpts = {};
1075
1207
  $.fn.spectrum.draggable = draggable;
1076
1208
  $.fn.spectrum.defaults = defaultOpts;
1209
+ $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
1210
+ if (typeof inputTypeColorSupport._cachedResult === "undefined") {
1211
+ var colorInput = $("<input type='color'/>")[0]; // if color element is supported, value will default to not null
1212
+ inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "";
1213
+ }
1214
+ return inputTypeColorSupport._cachedResult;
1215
+ };
1077
1216
 
1078
1217
  $.spectrum = { };
1079
1218
  $.spectrum.localization = { };
1080
1219
  $.spectrum.palettes = { };
1081
1220
 
1082
1221
  $.fn.spectrum.processNativeColorInputs = function () {
1083
- if (!inputTypeColorSupport) {
1084
- $("input[type=color]").spectrum({
1222
+ var colorInputs = $("input[type=color]");
1223
+ if (colorInputs.length && !inputTypeColorSupport()) {
1224
+ colorInputs.spectrum({
1085
1225
  preferredFormat: "hex6"
1086
1226
  });
1087
1227
  }
1088
1228
  };
1089
1229
 
1090
- // TinyColor v0.9.16
1230
+ // TinyColor v1.1.2
1091
1231
  // https://github.com/bgrins/TinyColor
1092
- // 2013-08-10, Brian Grinstead, MIT License
1232
+ // Brian Grinstead, MIT License
1093
1233
 
1094
1234
  (function() {
1095
1235
 
1096
- var trimLeft = /^[\s,#]+/,
1097
- trimRight = /\s+$/,
1098
- tinyCounter = 0,
1099
- math = Math,
1100
- mathRound = math.round,
1101
- mathMin = math.min,
1102
- mathMax = math.max,
1103
- mathRandom = math.random;
1236
+ var trimLeft = /^[\s,#]+/,
1237
+ trimRight = /\s+$/,
1238
+ tinyCounter = 0,
1239
+ math = Math,
1240
+ mathRound = math.round,
1241
+ mathMin = math.min,
1242
+ mathMax = math.max,
1243
+ mathRandom = math.random;
1104
1244
 
1105
- function tinycolor (color, opts) {
1245
+ var tinycolor = function(color, opts) {
1106
1246
 
1107
- color = (color) ? color : '';
1108
- opts = opts || { };
1247
+ color = (color) ? color : '';
1248
+ opts = opts || { };
1109
1249
 
1110
- // If input is already a tinycolor, return itself
1111
- if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
1112
- return color;
1113
- }
1250
+ // If input is already a tinycolor, return itself
1251
+ if (color instanceof tinycolor) {
1252
+ return color;
1253
+ }
1254
+ // If we are called as a function, call using new instead
1255
+ if (!(this instanceof tinycolor)) {
1256
+ return new tinycolor(color, opts);
1257
+ }
1114
1258
 
1115
- var rgb = inputToRGB(color);
1116
- var r = rgb.r,
1117
- g = rgb.g,
1118
- b = rgb.b,
1119
- a = rgb.a,
1120
- roundA = mathRound(100*a) / 100,
1121
- format = opts.format || rgb.format;
1259
+ var rgb = inputToRGB(color);
1260
+ this._originalInput = color;
1261
+ this._r = rgb.r;
1262
+ this._g = rgb.g;
1263
+ this._b = rgb.b;
1264
+ this._a = rgb.a;
1265
+ this._roundA = mathRound(1000 * this._a) / 1000;
1266
+ this._format = opts.format || rgb.format;
1267
+ this._gradientType = opts.gradientType;
1268
+
1269
+ // Don't let the range of [0,255] come back in [0,1].
1270
+ // Potentially lose a little bit of precision here, but will fix issues where
1271
+ // .5 gets interpreted as half of the total, instead of half of 1
1272
+ // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1273
+ if (this._r < 1) { this._r = mathRound(this._r); }
1274
+ if (this._g < 1) { this._g = mathRound(this._g); }
1275
+ if (this._b < 1) { this._b = mathRound(this._b); }
1276
+
1277
+ this._ok = rgb.ok;
1278
+ this._tc_id = tinyCounter++;
1279
+ };
1122
1280
 
1123
- // Don't let the range of [0,255] come back in [0,1].
1124
- // Potentially lose a little bit of precision here, but will fix issues where
1125
- // .5 gets interpreted as half of the total, instead of half of 1
1126
- // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1127
- if (r < 1) { r = mathRound(r); }
1128
- if (g < 1) { g = mathRound(g); }
1129
- if (b < 1) { b = mathRound(b); }
1281
+ tinycolor.prototype = {
1282
+ isDark: function() {
1283
+ return this.getBrightness() < 128;
1284
+ },
1285
+ isLight: function() {
1286
+ return !this.isDark();
1287
+ },
1288
+ isValid: function() {
1289
+ return this._ok;
1290
+ },
1291
+ getOriginalInput: function() {
1292
+ return this._originalInput;
1293
+ },
1294
+ getFormat: function() {
1295
+ return this._format;
1296
+ },
1297
+ getAlpha: function() {
1298
+ return this._a;
1299
+ },
1300
+ getBrightness: function() {
1301
+ var rgb = this.toRgb();
1302
+ return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
1303
+ },
1304
+ setAlpha: function(value) {
1305
+ this._a = boundAlpha(value);
1306
+ this._roundA = mathRound(1000 * this._a) / 1000;
1307
+ return this;
1308
+ },
1309
+ toHsv: function() {
1310
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1311
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
1312
+ },
1313
+ toHsvString: function() {
1314
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1315
+ var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
1316
+ return (this._a == 1) ?
1317
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
1318
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
1319
+ },
1320
+ toHsl: function() {
1321
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1322
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1323
+ },
1324
+ toHslString: function() {
1325
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1326
+ var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
1327
+ return (this._a == 1) ?
1328
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
1329
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
1330
+ },
1331
+ toHex: function(allow3Char) {
1332
+ return rgbToHex(this._r, this._g, this._b, allow3Char);
1333
+ },
1334
+ toHexString: function(allow3Char) {
1335
+ return '#' + this.toHex(allow3Char);
1336
+ },
1337
+ toHex8: function() {
1338
+ return rgbaToHex(this._r, this._g, this._b, this._a);
1339
+ },
1340
+ toHex8String: function() {
1341
+ return '#' + this.toHex8();
1342
+ },
1343
+ toRgb: function() {
1344
+ return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1345
+ },
1346
+ toRgbString: function() {
1347
+ return (this._a == 1) ?
1348
+ "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
1349
+ "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
1350
+ },
1351
+ toPercentageRgb: function() {
1352
+ return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
1353
+ },
1354
+ toPercentageRgbString: function() {
1355
+ return (this._a == 1) ?
1356
+ "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
1357
+ "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
1358
+ },
1359
+ toName: function() {
1360
+ if (this._a === 0) {
1361
+ return "transparent";
1362
+ }
1130
1363
 
1131
- return {
1132
- ok: rgb.ok,
1133
- format: format,
1134
- _tc_id: tinyCounter++,
1135
- alpha: a,
1136
- getAlpha: function() {
1137
- return a;
1138
- },
1139
- setAlpha: function(value) {
1140
- a = boundAlpha(value);
1141
- roundA = mathRound(100*a) / 100;
1142
- },
1143
- toHsv: function() {
1144
- var hsv = rgbToHsv(r, g, b);
1145
- return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };
1146
- },
1147
- toHsvString: function() {
1148
- var hsv = rgbToHsv(r, g, b);
1149
- var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
1150
- return (a == 1) ?
1151
- "hsv(" + h + ", " + s + "%, " + v + "%)" :
1152
- "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")";
1153
- },
1154
- toHsl: function() {
1155
- var hsl = rgbToHsl(r, g, b);
1156
- return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };
1157
- },
1158
- toHslString: function() {
1159
- var hsl = rgbToHsl(r, g, b);
1160
- var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
1161
- return (a == 1) ?
1162
- "hsl(" + h + ", " + s + "%, " + l + "%)" :
1163
- "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")";
1164
- },
1165
- toHex: function(allow3Char) {
1166
- return rgbToHex(r, g, b, allow3Char);
1167
- },
1168
- toHexString: function(allow3Char) {
1169
- return '#' + rgbToHex(r, g, b, allow3Char);
1170
- },
1171
- toRgb: function() {
1172
- return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };
1173
- },
1174
- toRgbString: function() {
1175
- return (a == 1) ?
1176
- "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
1177
- "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")";
1178
- },
1179
- toPercentageRgb: function() {
1180
- return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a };
1181
- },
1182
- toPercentageRgbString: function() {
1183
- return (a == 1) ?
1184
- "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" :
1185
- "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")";
1186
- },
1187
- toName: function() {
1188
- if (a === 0) {
1189
- return "transparent";
1190
- }
1364
+ if (this._a < 1) {
1365
+ return false;
1366
+ }
1191
1367
 
1192
- return hexNames[rgbToHex(r, g, b, true)] || false;
1193
- },
1194
- toFilter: function(secondColor) {
1195
- var hex = rgbToHex(r, g, b);
1196
- var secondHex = hex;
1197
- var alphaHex = Math.round(parseFloat(a) * 255).toString(16);
1198
- var secondAlphaHex = alphaHex;
1199
- var gradientType = opts && opts.gradientType ? "GradientType = 1, " : "";
1200
-
1201
- if (secondColor) {
1202
- var s = tinycolor(secondColor);
1203
- secondHex = s.toHex();
1204
- secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16);
1205
- }
1368
+ return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1369
+ },
1370
+ toFilter: function(secondColor) {
1371
+ var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
1372
+ var secondHex8String = hex8String;
1373
+ var gradientType = this._gradientType ? "GradientType = 1, " : "";
1206
1374
 
1207
- return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")";
1208
- },
1209
- toString: function(format) {
1210
- var formatSet = !!format;
1211
- format = format || this.format;
1375
+ if (secondColor) {
1376
+ var s = tinycolor(secondColor);
1377
+ secondHex8String = s.toHex8String();
1378
+ }
1212
1379
 
1213
- var formattedString = false;
1214
- var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;
1215
- var formatWithAlpha = hasAlphaAndFormatNotSet && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
1380
+ return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
1381
+ },
1382
+ toString: function(format) {
1383
+ var formatSet = !!format;
1384
+ format = format || this._format;
1385
+
1386
+ var formattedString = false;
1387
+ var hasAlpha = this._a < 1 && this._a >= 0;
1388
+ var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
1389
+
1390
+ if (needsAlphaFormat) {
1391
+ // Special case for "transparent", all other non-alpha formats
1392
+ // will return rgba when there is transparency.
1393
+ if (format === "name" && this._a === 0) {
1394
+ return this.toName();
1395
+ }
1396
+ return this.toRgbString();
1397
+ }
1398
+ if (format === "rgb") {
1399
+ formattedString = this.toRgbString();
1400
+ }
1401
+ if (format === "prgb") {
1402
+ formattedString = this.toPercentageRgbString();
1403
+ }
1404
+ if (format === "hex" || format === "hex6") {
1405
+ formattedString = this.toHexString();
1406
+ }
1407
+ if (format === "hex3") {
1408
+ formattedString = this.toHexString(true);
1409
+ }
1410
+ if (format === "hex8") {
1411
+ formattedString = this.toHex8String();
1412
+ }
1413
+ if (format === "name") {
1414
+ formattedString = this.toName();
1415
+ }
1416
+ if (format === "hsl") {
1417
+ formattedString = this.toHslString();
1418
+ }
1419
+ if (format === "hsv") {
1420
+ formattedString = this.toHsvString();
1421
+ }
1216
1422
 
1217
- if (format === "rgb") {
1218
- formattedString = this.toRgbString();
1219
- }
1220
- if (format === "prgb") {
1221
- formattedString = this.toPercentageRgbString();
1222
- }
1223
- if (format === "hex" || format === "hex6") {
1224
- formattedString = this.toHexString();
1225
- }
1226
- if (format === "hex3") {
1227
- formattedString = this.toHexString(true);
1228
- }
1229
- if (format === "name") {
1230
- formattedString = this.toName();
1231
- }
1232
- if (format === "hsl") {
1233
- formattedString = this.toHslString();
1234
- }
1235
- if (format === "hsv") {
1236
- formattedString = this.toHsvString();
1237
- }
1423
+ return formattedString || this.toHexString();
1424
+ },
1238
1425
 
1239
- if (formatWithAlpha) {
1240
- return this.toRgbString();
1241
- }
1426
+ _applyModification: function(fn, args) {
1427
+ var color = fn.apply(null, [this].concat([].slice.call(args)));
1428
+ this._r = color._r;
1429
+ this._g = color._g;
1430
+ this._b = color._b;
1431
+ this.setAlpha(color._a);
1432
+ return this;
1433
+ },
1434
+ lighten: function() {
1435
+ return this._applyModification(lighten, arguments);
1436
+ },
1437
+ brighten: function() {
1438
+ return this._applyModification(brighten, arguments);
1439
+ },
1440
+ darken: function() {
1441
+ return this._applyModification(darken, arguments);
1442
+ },
1443
+ desaturate: function() {
1444
+ return this._applyModification(desaturate, arguments);
1445
+ },
1446
+ saturate: function() {
1447
+ return this._applyModification(saturate, arguments);
1448
+ },
1449
+ greyscale: function() {
1450
+ return this._applyModification(greyscale, arguments);
1451
+ },
1452
+ spin: function() {
1453
+ return this._applyModification(spin, arguments);
1454
+ },
1242
1455
 
1243
- return formattedString || this.toHexString();
1244
- }
1245
- };
1456
+ _applyCombination: function(fn, args) {
1457
+ return fn.apply(null, [this].concat([].slice.call(args)));
1458
+ },
1459
+ analogous: function() {
1460
+ return this._applyCombination(analogous, arguments);
1461
+ },
1462
+ complement: function() {
1463
+ return this._applyCombination(complement, arguments);
1464
+ },
1465
+ monochromatic: function() {
1466
+ return this._applyCombination(monochromatic, arguments);
1467
+ },
1468
+ splitcomplement: function() {
1469
+ return this._applyCombination(splitcomplement, arguments);
1470
+ },
1471
+ triad: function() {
1472
+ return this._applyCombination(triad, arguments);
1473
+ },
1474
+ tetrad: function() {
1475
+ return this._applyCombination(tetrad, arguments);
1246
1476
  }
1477
+ };
1247
1478
 
1248
- // If input is an object, force 1 into "1.0" to handle ratios properly
1249
- // String input requires "1.0" as input, so 1 will be treated as 1
1250
- tinycolor.fromRatio = function(color, opts) {
1251
- if (typeof color == "object") {
1252
- var newColor = {};
1253
- for (var i in color) {
1254
- if (color.hasOwnProperty(i)) {
1255
- if (i === "a") {
1256
- newColor[i] = color[i];
1257
- }
1258
- else {
1259
- newColor[i] = convertToPercentage(color[i]);
1260
- }
1479
+ // If input is an object, force 1 into "1.0" to handle ratios properly
1480
+ // String input requires "1.0" as input, so 1 will be treated as 1
1481
+ tinycolor.fromRatio = function(color, opts) {
1482
+ if (typeof color == "object") {
1483
+ var newColor = {};
1484
+ for (var i in color) {
1485
+ if (color.hasOwnProperty(i)) {
1486
+ if (i === "a") {
1487
+ newColor[i] = color[i];
1488
+ }
1489
+ else {
1490
+ newColor[i] = convertToPercentage(color[i]);
1261
1491
  }
1262
1492
  }
1263
- color = newColor;
1264
1493
  }
1494
+ color = newColor;
1495
+ }
1265
1496
 
1266
- return tinycolor(color, opts);
1267
- };
1497
+ return tinycolor(color, opts);
1498
+ };
1268
1499
 
1269
- // Given a string or object, convert that input to RGB
1270
- // Possible string inputs:
1271
- //
1272
- // "red"
1273
- // "#f00" or "f00"
1274
- // "#ff0000" or "ff0000"
1275
- // "rgb 255 0 0" or "rgb (255, 0, 0)"
1276
- // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1277
- // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1278
- // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1279
- // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1280
- // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1281
- // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1282
- //
1283
- function inputToRGB(color) {
1284
-
1285
- var rgb = { r: 0, g: 0, b: 0 };
1286
- var a = 1;
1287
- var ok = false;
1288
- var format = false;
1289
-
1290
- if (typeof color == "string") {
1291
- color = stringInputToObject(color);
1292
- }
1293
-
1294
- if (typeof color == "object") {
1295
- if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1296
- rgb = rgbToRgb(color.r, color.g, color.b);
1297
- ok = true;
1298
- format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1299
- }
1300
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1301
- color.s = convertToPercentage(color.s);
1302
- color.v = convertToPercentage(color.v);
1303
- rgb = hsvToRgb(color.h, color.s, color.v);
1304
- ok = true;
1305
- format = "hsv";
1306
- }
1307
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1308
- color.s = convertToPercentage(color.s);
1309
- color.l = convertToPercentage(color.l);
1310
- rgb = hslToRgb(color.h, color.s, color.l);
1311
- ok = true;
1312
- format = "hsl";
1313
- }
1500
+ // Given a string or object, convert that input to RGB
1501
+ // Possible string inputs:
1502
+ //
1503
+ // "red"
1504
+ // "#f00" or "f00"
1505
+ // "#ff0000" or "ff0000"
1506
+ // "#ff000000" or "ff000000"
1507
+ // "rgb 255 0 0" or "rgb (255, 0, 0)"
1508
+ // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1509
+ // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1510
+ // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1511
+ // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1512
+ // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1513
+ // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1514
+ //
1515
+ function inputToRGB(color) {
1516
+
1517
+ var rgb = { r: 0, g: 0, b: 0 };
1518
+ var a = 1;
1519
+ var ok = false;
1520
+ var format = false;
1521
+
1522
+ if (typeof color == "string") {
1523
+ color = stringInputToObject(color);
1524
+ }
1314
1525
 
1315
- if (color.hasOwnProperty("a")) {
1316
- a = color.a;
1317
- }
1526
+ if (typeof color == "object") {
1527
+ if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1528
+ rgb = rgbToRgb(color.r, color.g, color.b);
1529
+ ok = true;
1530
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1531
+ }
1532
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1533
+ color.s = convertToPercentage(color.s);
1534
+ color.v = convertToPercentage(color.v);
1535
+ rgb = hsvToRgb(color.h, color.s, color.v);
1536
+ ok = true;
1537
+ format = "hsv";
1538
+ }
1539
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1540
+ color.s = convertToPercentage(color.s);
1541
+ color.l = convertToPercentage(color.l);
1542
+ rgb = hslToRgb(color.h, color.s, color.l);
1543
+ ok = true;
1544
+ format = "hsl";
1318
1545
  }
1319
1546
 
1320
- a = boundAlpha(a);
1321
-
1322
- return {
1323
- ok: ok,
1324
- format: color.format || format,
1325
- r: mathMin(255, mathMax(rgb.r, 0)),
1326
- g: mathMin(255, mathMax(rgb.g, 0)),
1327
- b: mathMin(255, mathMax(rgb.b, 0)),
1328
- a: a
1329
- };
1547
+ if (color.hasOwnProperty("a")) {
1548
+ a = color.a;
1549
+ }
1330
1550
  }
1331
1551
 
1552
+ a = boundAlpha(a);
1553
+
1554
+ return {
1555
+ ok: ok,
1556
+ format: color.format || format,
1557
+ r: mathMin(255, mathMax(rgb.r, 0)),
1558
+ g: mathMin(255, mathMax(rgb.g, 0)),
1559
+ b: mathMin(255, mathMax(rgb.b, 0)),
1560
+ a: a
1561
+ };
1562
+ }
1332
1563
 
1333
- // Conversion Functions
1334
- // --------------------
1335
1564
 
1336
- // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1337
- // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1565
+ // Conversion Functions
1566
+ // --------------------
1338
1567
 
1339
- // `rgbToRgb`
1340
- // Handle bounds / percentage checking to conform to CSS color spec
1341
- // <http://www.w3.org/TR/css3-color/>
1342
- // *Assumes:* r, g, b in [0, 255] or [0, 1]
1343
- // *Returns:* { r, g, b } in [0, 255]
1344
- function rgbToRgb(r, g, b){
1345
- return {
1346
- r: bound01(r, 255) * 255,
1347
- g: bound01(g, 255) * 255,
1348
- b: bound01(b, 255) * 255
1349
- };
1350
- }
1568
+ // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1569
+ // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1351
1570
 
1352
- // `rgbToHsl`
1353
- // Converts an RGB color value to HSL.
1354
- // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1355
- // *Returns:* { h, s, l } in [0,1]
1356
- function rgbToHsl(r, g, b) {
1571
+ // `rgbToRgb`
1572
+ // Handle bounds / percentage checking to conform to CSS color spec
1573
+ // <http://www.w3.org/TR/css3-color/>
1574
+ // *Assumes:* r, g, b in [0, 255] or [0, 1]
1575
+ // *Returns:* { r, g, b } in [0, 255]
1576
+ function rgbToRgb(r, g, b){
1577
+ return {
1578
+ r: bound01(r, 255) * 255,
1579
+ g: bound01(g, 255) * 255,
1580
+ b: bound01(b, 255) * 255
1581
+ };
1582
+ }
1357
1583
 
1358
- r = bound01(r, 255);
1359
- g = bound01(g, 255);
1360
- b = bound01(b, 255);
1584
+ // `rgbToHsl`
1585
+ // Converts an RGB color value to HSL.
1586
+ // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1587
+ // *Returns:* { h, s, l } in [0,1]
1588
+ function rgbToHsl(r, g, b) {
1361
1589
 
1362
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
1363
- var h, s, l = (max + min) / 2;
1590
+ r = bound01(r, 255);
1591
+ g = bound01(g, 255);
1592
+ b = bound01(b, 255);
1364
1593
 
1365
- if(max == min) {
1366
- h = s = 0; // achromatic
1367
- }
1368
- else {
1369
- var d = max - min;
1370
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1371
- switch(max) {
1372
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1373
- case g: h = (b - r) / d + 2; break;
1374
- case b: h = (r - g) / d + 4; break;
1375
- }
1594
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1595
+ var h, s, l = (max + min) / 2;
1376
1596
 
1377
- h /= 6;
1597
+ if(max == min) {
1598
+ h = s = 0; // achromatic
1599
+ }
1600
+ else {
1601
+ var d = max - min;
1602
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1603
+ switch(max) {
1604
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1605
+ case g: h = (b - r) / d + 2; break;
1606
+ case b: h = (r - g) / d + 4; break;
1378
1607
  }
1379
1608
 
1380
- return { h: h, s: s, l: l };
1609
+ h /= 6;
1381
1610
  }
1382
1611
 
1383
- // `hslToRgb`
1384
- // Converts an HSL color value to RGB.
1385
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1386
- // *Returns:* { r, g, b } in the set [0, 255]
1387
- function hslToRgb(h, s, l) {
1388
- var r, g, b;
1389
-
1390
- h = bound01(h, 360);
1391
- s = bound01(s, 100);
1392
- l = bound01(l, 100);
1393
-
1394
- function hue2rgb(p, q, t) {
1395
- if(t < 0) t += 1;
1396
- if(t > 1) t -= 1;
1397
- if(t < 1/6) return p + (q - p) * 6 * t;
1398
- if(t < 1/2) return q;
1399
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1400
- return p;
1401
- }
1612
+ return { h: h, s: s, l: l };
1613
+ }
1402
1614
 
1403
- if(s === 0) {
1404
- r = g = b = l; // achromatic
1405
- }
1406
- else {
1407
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1408
- var p = 2 * l - q;
1409
- r = hue2rgb(p, q, h + 1/3);
1410
- g = hue2rgb(p, q, h);
1411
- b = hue2rgb(p, q, h - 1/3);
1412
- }
1615
+ // `hslToRgb`
1616
+ // Converts an HSL color value to RGB.
1617
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1618
+ // *Returns:* { r, g, b } in the set [0, 255]
1619
+ function hslToRgb(h, s, l) {
1620
+ var r, g, b;
1621
+
1622
+ h = bound01(h, 360);
1623
+ s = bound01(s, 100);
1624
+ l = bound01(l, 100);
1625
+
1626
+ function hue2rgb(p, q, t) {
1627
+ if(t < 0) t += 1;
1628
+ if(t > 1) t -= 1;
1629
+ if(t < 1/6) return p + (q - p) * 6 * t;
1630
+ if(t < 1/2) return q;
1631
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1632
+ return p;
1633
+ }
1413
1634
 
1414
- return { r: r * 255, g: g * 255, b: b * 255 };
1635
+ if(s === 0) {
1636
+ r = g = b = l; // achromatic
1637
+ }
1638
+ else {
1639
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1640
+ var p = 2 * l - q;
1641
+ r = hue2rgb(p, q, h + 1/3);
1642
+ g = hue2rgb(p, q, h);
1643
+ b = hue2rgb(p, q, h - 1/3);
1415
1644
  }
1416
1645
 
1417
- // `rgbToHsv`
1418
- // Converts an RGB color value to HSV
1419
- // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1420
- // *Returns:* { h, s, v } in [0,1]
1421
- function rgbToHsv(r, g, b) {
1646
+ return { r: r * 255, g: g * 255, b: b * 255 };
1647
+ }
1422
1648
 
1423
- r = bound01(r, 255);
1424
- g = bound01(g, 255);
1425
- b = bound01(b, 255);
1649
+ // `rgbToHsv`
1650
+ // Converts an RGB color value to HSV
1651
+ // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1652
+ // *Returns:* { h, s, v } in [0,1]
1653
+ function rgbToHsv(r, g, b) {
1426
1654
 
1427
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
1428
- var h, s, v = max;
1655
+ r = bound01(r, 255);
1656
+ g = bound01(g, 255);
1657
+ b = bound01(b, 255);
1429
1658
 
1430
- var d = max - min;
1431
- s = max === 0 ? 0 : d / max;
1659
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1660
+ var h, s, v = max;
1432
1661
 
1433
- if(max == min) {
1434
- h = 0; // achromatic
1435
- }
1436
- else {
1437
- switch(max) {
1438
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1439
- case g: h = (b - r) / d + 2; break;
1440
- case b: h = (r - g) / d + 4; break;
1441
- }
1442
- h /= 6;
1662
+ var d = max - min;
1663
+ s = max === 0 ? 0 : d / max;
1664
+
1665
+ if(max == min) {
1666
+ h = 0; // achromatic
1667
+ }
1668
+ else {
1669
+ switch(max) {
1670
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1671
+ case g: h = (b - r) / d + 2; break;
1672
+ case b: h = (r - g) / d + 4; break;
1443
1673
  }
1444
- return { h: h, s: s, v: v };
1674
+ h /= 6;
1445
1675
  }
1676
+ return { h: h, s: s, v: v };
1677
+ }
1446
1678
 
1447
- // `hsvToRgb`
1448
- // Converts an HSV color value to RGB.
1449
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1450
- // *Returns:* { r, g, b } in the set [0, 255]
1451
- function hsvToRgb(h, s, v) {
1452
-
1453
- h = bound01(h, 360) * 6;
1454
- s = bound01(s, 100);
1455
- v = bound01(v, 100);
1456
-
1457
- var i = math.floor(h),
1458
- f = h - i,
1459
- p = v * (1 - s),
1460
- q = v * (1 - f * s),
1461
- t = v * (1 - (1 - f) * s),
1462
- mod = i % 6,
1463
- r = [v, q, p, p, t, v][mod],
1464
- g = [t, v, v, q, p, p][mod],
1465
- b = [p, p, t, v, v, q][mod];
1679
+ // `hsvToRgb`
1680
+ // Converts an HSV color value to RGB.
1681
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1682
+ // *Returns:* { r, g, b } in the set [0, 255]
1683
+ function hsvToRgb(h, s, v) {
1684
+
1685
+ h = bound01(h, 360) * 6;
1686
+ s = bound01(s, 100);
1687
+ v = bound01(v, 100);
1688
+
1689
+ var i = math.floor(h),
1690
+ f = h - i,
1691
+ p = v * (1 - s),
1692
+ q = v * (1 - f * s),
1693
+ t = v * (1 - (1 - f) * s),
1694
+ mod = i % 6,
1695
+ r = [v, q, p, p, t, v][mod],
1696
+ g = [t, v, v, q, p, p][mod],
1697
+ b = [p, p, t, v, v, q][mod];
1698
+
1699
+ return { r: r * 255, g: g * 255, b: b * 255 };
1700
+ }
1466
1701
 
1467
- return { r: r * 255, g: g * 255, b: b * 255 };
1702
+ // `rgbToHex`
1703
+ // Converts an RGB color to hex
1704
+ // Assumes r, g, and b are contained in the set [0, 255]
1705
+ // Returns a 3 or 6 character hex
1706
+ function rgbToHex(r, g, b, allow3Char) {
1707
+
1708
+ var hex = [
1709
+ pad2(mathRound(r).toString(16)),
1710
+ pad2(mathRound(g).toString(16)),
1711
+ pad2(mathRound(b).toString(16))
1712
+ ];
1713
+
1714
+ // Return a 3 character hex if possible
1715
+ if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
1716
+ return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1468
1717
  }
1469
1718
 
1470
- // `rgbToHex`
1471
- // Converts an RGB color to hex
1472
- // Assumes r, g, and b are contained in the set [0, 255]
1473
- // Returns a 3 or 6 character hex
1474
- function rgbToHex(r, g, b, allow3Char) {
1719
+ return hex.join("");
1720
+ }
1721
+ // `rgbaToHex`
1722
+ // Converts an RGBA color plus alpha transparency to hex
1723
+ // Assumes r, g, b and a are contained in the set [0, 255]
1724
+ // Returns an 8 character hex
1725
+ function rgbaToHex(r, g, b, a) {
1475
1726
 
1476
1727
  var hex = [
1728
+ pad2(convertDecimalToHex(a)),
1477
1729
  pad2(mathRound(r).toString(16)),
1478
1730
  pad2(mathRound(g).toString(16)),
1479
1731
  pad2(mathRound(b).toString(16))
1480
1732
  ];
1481
1733
 
1482
- // Return a 3 character hex if possible
1483
- if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
1484
- return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1485
- }
1486
-
1487
1734
  return hex.join("");
1488
1735
  }
1489
1736
 
1490
- // `equals`
1491
- // Can be called with any tinycolor input
1492
- tinycolor.equals = function (color1, color2) {
1493
- if (!color1 || !color2) { return false; }
1494
- return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1495
- };
1496
- tinycolor.random = function() {
1497
- return tinycolor.fromRatio({
1498
- r: mathRandom(),
1499
- g: mathRandom(),
1500
- b: mathRandom()
1501
- });
1502
- };
1737
+ // `equals`
1738
+ // Can be called with any tinycolor input
1739
+ tinycolor.equals = function (color1, color2) {
1740
+ if (!color1 || !color2) { return false; }
1741
+ return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1742
+ };
1743
+ tinycolor.random = function() {
1744
+ return tinycolor.fromRatio({
1745
+ r: mathRandom(),
1746
+ g: mathRandom(),
1747
+ b: mathRandom()
1748
+ });
1749
+ };
1503
1750
 
1504
1751
 
1505
- // Modification Functions
1506
- // ----------------------
1507
- // Thanks to less.js for some of the basics here
1508
- // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1752
+ // Modification Functions
1753
+ // ----------------------
1754
+ // Thanks to less.js for some of the basics here
1755
+ // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1509
1756
 
1510
- tinycolor.desaturate = function (color, amount) {
1511
- amount = (amount === 0) ? 0 : (amount || 10);
1512
- var hsl = tinycolor(color).toHsl();
1513
- hsl.s -= amount / 100;
1514
- hsl.s = clamp01(hsl.s);
1515
- return tinycolor(hsl);
1516
- };
1517
- tinycolor.saturate = function (color, amount) {
1518
- amount = (amount === 0) ? 0 : (amount || 10);
1519
- var hsl = tinycolor(color).toHsl();
1520
- hsl.s += amount / 100;
1521
- hsl.s = clamp01(hsl.s);
1522
- return tinycolor(hsl);
1523
- };
1524
- tinycolor.greyscale = function(color) {
1525
- return tinycolor.desaturate(color, 100);
1526
- };
1527
- tinycolor.lighten = function(color, amount) {
1528
- amount = (amount === 0) ? 0 : (amount || 10);
1529
- var hsl = tinycolor(color).toHsl();
1530
- hsl.l += amount / 100;
1531
- hsl.l = clamp01(hsl.l);
1532
- return tinycolor(hsl);
1533
- };
1534
- tinycolor.darken = function (color, amount) {
1535
- amount = (amount === 0) ? 0 : (amount || 10);
1536
- var hsl = tinycolor(color).toHsl();
1537
- hsl.l -= amount / 100;
1538
- hsl.l = clamp01(hsl.l);
1539
- return tinycolor(hsl);
1540
- };
1541
- tinycolor.complement = function(color) {
1542
- var hsl = tinycolor(color).toHsl();
1543
- hsl.h = (hsl.h + 180) % 360;
1544
- return tinycolor(hsl);
1545
- };
1757
+ function desaturate(color, amount) {
1758
+ amount = (amount === 0) ? 0 : (amount || 10);
1759
+ var hsl = tinycolor(color).toHsl();
1760
+ hsl.s -= amount / 100;
1761
+ hsl.s = clamp01(hsl.s);
1762
+ return tinycolor(hsl);
1763
+ }
1546
1764
 
1765
+ function saturate(color, amount) {
1766
+ amount = (amount === 0) ? 0 : (amount || 10);
1767
+ var hsl = tinycolor(color).toHsl();
1768
+ hsl.s += amount / 100;
1769
+ hsl.s = clamp01(hsl.s);
1770
+ return tinycolor(hsl);
1771
+ }
1547
1772
 
1548
- // Combination Functions
1549
- // ---------------------
1550
- // Thanks to jQuery xColor for some of the ideas behind these
1551
- // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1773
+ function greyscale(color) {
1774
+ return tinycolor(color).desaturate(100);
1775
+ }
1552
1776
 
1553
- tinycolor.triad = function(color) {
1554
- var hsl = tinycolor(color).toHsl();
1555
- var h = hsl.h;
1556
- return [
1557
- tinycolor(color),
1558
- tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1559
- tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1560
- ];
1561
- };
1562
- tinycolor.tetrad = function(color) {
1563
- var hsl = tinycolor(color).toHsl();
1564
- var h = hsl.h;
1565
- return [
1566
- tinycolor(color),
1567
- tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1568
- tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1569
- tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1570
- ];
1571
- };
1572
- tinycolor.splitcomplement = function(color) {
1573
- var hsl = tinycolor(color).toHsl();
1574
- var h = hsl.h;
1575
- return [
1576
- tinycolor(color),
1577
- tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1578
- tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1579
- ];
1580
- };
1581
- tinycolor.analogous = function(color, results, slices) {
1582
- results = results || 6;
1583
- slices = slices || 30;
1777
+ function lighten (color, amount) {
1778
+ amount = (amount === 0) ? 0 : (amount || 10);
1779
+ var hsl = tinycolor(color).toHsl();
1780
+ hsl.l += amount / 100;
1781
+ hsl.l = clamp01(hsl.l);
1782
+ return tinycolor(hsl);
1783
+ }
1584
1784
 
1585
- var hsl = tinycolor(color).toHsl();
1586
- var part = 360 / slices;
1587
- var ret = [tinycolor(color)];
1785
+ function brighten(color, amount) {
1786
+ amount = (amount === 0) ? 0 : (amount || 10);
1787
+ var rgb = tinycolor(color).toRgb();
1788
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
1789
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
1790
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
1791
+ return tinycolor(rgb);
1792
+ }
1588
1793
 
1589
- for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1590
- hsl.h = (hsl.h + part) % 360;
1591
- ret.push(tinycolor(hsl));
1592
- }
1593
- return ret;
1594
- };
1595
- tinycolor.monochromatic = function(color, results) {
1596
- results = results || 6;
1597
- var hsv = tinycolor(color).toHsv();
1598
- var h = hsv.h, s = hsv.s, v = hsv.v;
1599
- var ret = [];
1600
- var modification = 1 / results;
1794
+ function darken (color, amount) {
1795
+ amount = (amount === 0) ? 0 : (amount || 10);
1796
+ var hsl = tinycolor(color).toHsl();
1797
+ hsl.l -= amount / 100;
1798
+ hsl.l = clamp01(hsl.l);
1799
+ return tinycolor(hsl);
1800
+ }
1601
1801
 
1602
- while (results--) {
1603
- ret.push(tinycolor({ h: h, s: s, v: v}));
1604
- v = (v + modification) % 1;
1605
- }
1802
+ // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
1803
+ // Values outside of this range will be wrapped into this range.
1804
+ function spin(color, amount) {
1805
+ var hsl = tinycolor(color).toHsl();
1806
+ var hue = (mathRound(hsl.h) + amount) % 360;
1807
+ hsl.h = hue < 0 ? 360 + hue : hue;
1808
+ return tinycolor(hsl);
1809
+ }
1606
1810
 
1607
- return ret;
1608
- };
1811
+ // Combination Functions
1812
+ // ---------------------
1813
+ // Thanks to jQuery xColor for some of the ideas behind these
1814
+ // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1609
1815
 
1816
+ function complement(color) {
1817
+ var hsl = tinycolor(color).toHsl();
1818
+ hsl.h = (hsl.h + 180) % 360;
1819
+ return tinycolor(hsl);
1820
+ }
1610
1821
 
1611
- // Readability Functions
1612
- // ---------------------
1613
- // <http://www.w3.org/TR/AERT#color-contrast>
1614
-
1615
- // `readability`
1616
- // Analyze the 2 colors and returns an object with the following properties:
1617
- // `brightness`: difference in brightness between the two colors
1618
- // `color`: difference in color/hue between the two colors
1619
- tinycolor.readability = function(color1, color2) {
1620
- var a = tinycolor(color1).toRgb();
1621
- var b = tinycolor(color2).toRgb();
1622
- var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
1623
- var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
1624
- var colorDiff = (
1625
- Math.max(a.r, b.r) - Math.min(a.r, b.r) +
1626
- Math.max(a.g, b.g) - Math.min(a.g, b.g) +
1627
- Math.max(a.b, b.b) - Math.min(a.b, b.b)
1628
- );
1822
+ function triad(color) {
1823
+ var hsl = tinycolor(color).toHsl();
1824
+ var h = hsl.h;
1825
+ return [
1826
+ tinycolor(color),
1827
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1828
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1829
+ ];
1830
+ }
1629
1831
 
1630
- return {
1631
- brightness: Math.abs(brightnessA - brightnessB),
1632
- color: colorDiff
1633
- };
1634
- };
1832
+ function tetrad(color) {
1833
+ var hsl = tinycolor(color).toHsl();
1834
+ var h = hsl.h;
1835
+ return [
1836
+ tinycolor(color),
1837
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1838
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1839
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1840
+ ];
1841
+ }
1635
1842
 
1636
- // `readable`
1637
- // http://www.w3.org/TR/AERT#color-contrast
1638
- // Ensure that foreground and background color combinations provide sufficient contrast.
1639
- // *Example*
1640
- // tinycolor.readable("#000", "#111") => false
1641
- tinycolor.readable = function(color1, color2) {
1642
- var readability = tinycolor.readability(color1, color2);
1643
- return readability.brightness > 125 && readability.color > 500;
1644
- };
1843
+ function splitcomplement(color) {
1844
+ var hsl = tinycolor(color).toHsl();
1845
+ var h = hsl.h;
1846
+ return [
1847
+ tinycolor(color),
1848
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1849
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1850
+ ];
1851
+ }
1645
1852
 
1646
- // `mostReadable`
1647
- // Given a base color and a list of possible foreground or background
1648
- // colors for that base, returns the most readable color.
1649
- // *Example*
1650
- // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1651
- tinycolor.mostReadable = function(baseColor, colorList) {
1652
- var bestColor = null;
1653
- var bestScore = 0;
1654
- var bestIsReadable = false;
1655
- for (var i=0; i < colorList.length; i++) {
1656
-
1657
- // We normalize both around the "acceptable" breaking point,
1658
- // but rank brightness constrast higher than hue.
1659
-
1660
- var readability = tinycolor.readability(baseColor, colorList[i]);
1661
- var readable = readability.brightness > 125 && readability.color > 500;
1662
- var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1663
-
1664
- if ((readable && ! bestIsReadable) ||
1665
- (readable && bestIsReadable && score > bestScore) ||
1666
- ((! readable) && (! bestIsReadable) && score > bestScore)) {
1667
- bestIsReadable = readable;
1668
- bestScore = score;
1669
- bestColor = tinycolor(colorList[i]);
1670
- }
1671
- }
1672
- return bestColor;
1673
- };
1853
+ function analogous(color, results, slices) {
1854
+ results = results || 6;
1855
+ slices = slices || 30;
1856
+
1857
+ var hsl = tinycolor(color).toHsl();
1858
+ var part = 360 / slices;
1859
+ var ret = [tinycolor(color)];
1860
+
1861
+ for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1862
+ hsl.h = (hsl.h + part) % 360;
1863
+ ret.push(tinycolor(hsl));
1864
+ }
1865
+ return ret;
1866
+ }
1674
1867
 
1868
+ function monochromatic(color, results) {
1869
+ results = results || 6;
1870
+ var hsv = tinycolor(color).toHsv();
1871
+ var h = hsv.h, s = hsv.s, v = hsv.v;
1872
+ var ret = [];
1873
+ var modification = 1 / results;
1675
1874
 
1676
- // Big List of Colors
1677
- // ------------------
1678
- // <http://www.w3.org/TR/css3-color/#svg-color>
1679
- var names = tinycolor.names = {
1680
- aliceblue: "f0f8ff",
1681
- antiquewhite: "faebd7",
1682
- aqua: "0ff",
1683
- aquamarine: "7fffd4",
1684
- azure: "f0ffff",
1685
- beige: "f5f5dc",
1686
- bisque: "ffe4c4",
1687
- black: "000",
1688
- blanchedalmond: "ffebcd",
1689
- blue: "00f",
1690
- blueviolet: "8a2be2",
1691
- brown: "a52a2a",
1692
- burlywood: "deb887",
1693
- burntsienna: "ea7e5d",
1694
- cadetblue: "5f9ea0",
1695
- chartreuse: "7fff00",
1696
- chocolate: "d2691e",
1697
- coral: "ff7f50",
1698
- cornflowerblue: "6495ed",
1699
- cornsilk: "fff8dc",
1700
- crimson: "dc143c",
1701
- cyan: "0ff",
1702
- darkblue: "00008b",
1703
- darkcyan: "008b8b",
1704
- darkgoldenrod: "b8860b",
1705
- darkgray: "a9a9a9",
1706
- darkgreen: "006400",
1707
- darkgrey: "a9a9a9",
1708
- darkkhaki: "bdb76b",
1709
- darkmagenta: "8b008b",
1710
- darkolivegreen: "556b2f",
1711
- darkorange: "ff8c00",
1712
- darkorchid: "9932cc",
1713
- darkred: "8b0000",
1714
- darksalmon: "e9967a",
1715
- darkseagreen: "8fbc8f",
1716
- darkslateblue: "483d8b",
1717
- darkslategray: "2f4f4f",
1718
- darkslategrey: "2f4f4f",
1719
- darkturquoise: "00ced1",
1720
- darkviolet: "9400d3",
1721
- deeppink: "ff1493",
1722
- deepskyblue: "00bfff",
1723
- dimgray: "696969",
1724
- dimgrey: "696969",
1725
- dodgerblue: "1e90ff",
1726
- firebrick: "b22222",
1727
- floralwhite: "fffaf0",
1728
- forestgreen: "228b22",
1729
- fuchsia: "f0f",
1730
- gainsboro: "dcdcdc",
1731
- ghostwhite: "f8f8ff",
1732
- gold: "ffd700",
1733
- goldenrod: "daa520",
1734
- gray: "808080",
1735
- green: "008000",
1736
- greenyellow: "adff2f",
1737
- grey: "808080",
1738
- honeydew: "f0fff0",
1739
- hotpink: "ff69b4",
1740
- indianred: "cd5c5c",
1741
- indigo: "4b0082",
1742
- ivory: "fffff0",
1743
- khaki: "f0e68c",
1744
- lavender: "e6e6fa",
1745
- lavenderblush: "fff0f5",
1746
- lawngreen: "7cfc00",
1747
- lemonchiffon: "fffacd",
1748
- lightblue: "add8e6",
1749
- lightcoral: "f08080",
1750
- lightcyan: "e0ffff",
1751
- lightgoldenrodyellow: "fafad2",
1752
- lightgray: "d3d3d3",
1753
- lightgreen: "90ee90",
1754
- lightgrey: "d3d3d3",
1755
- lightpink: "ffb6c1",
1756
- lightsalmon: "ffa07a",
1757
- lightseagreen: "20b2aa",
1758
- lightskyblue: "87cefa",
1759
- lightslategray: "789",
1760
- lightslategrey: "789",
1761
- lightsteelblue: "b0c4de",
1762
- lightyellow: "ffffe0",
1763
- lime: "0f0",
1764
- limegreen: "32cd32",
1765
- linen: "faf0e6",
1766
- magenta: "f0f",
1767
- maroon: "800000",
1768
- mediumaquamarine: "66cdaa",
1769
- mediumblue: "0000cd",
1770
- mediumorchid: "ba55d3",
1771
- mediumpurple: "9370db",
1772
- mediumseagreen: "3cb371",
1773
- mediumslateblue: "7b68ee",
1774
- mediumspringgreen: "00fa9a",
1775
- mediumturquoise: "48d1cc",
1776
- mediumvioletred: "c71585",
1777
- midnightblue: "191970",
1778
- mintcream: "f5fffa",
1779
- mistyrose: "ffe4e1",
1780
- moccasin: "ffe4b5",
1781
- navajowhite: "ffdead",
1782
- navy: "000080",
1783
- oldlace: "fdf5e6",
1784
- olive: "808000",
1785
- olivedrab: "6b8e23",
1786
- orange: "ffa500",
1787
- orangered: "ff4500",
1788
- orchid: "da70d6",
1789
- palegoldenrod: "eee8aa",
1790
- palegreen: "98fb98",
1791
- paleturquoise: "afeeee",
1792
- palevioletred: "db7093",
1793
- papayawhip: "ffefd5",
1794
- peachpuff: "ffdab9",
1795
- peru: "cd853f",
1796
- pink: "ffc0cb",
1797
- plum: "dda0dd",
1798
- powderblue: "b0e0e6",
1799
- purple: "800080",
1800
- red: "f00",
1801
- rosybrown: "bc8f8f",
1802
- royalblue: "4169e1",
1803
- saddlebrown: "8b4513",
1804
- salmon: "fa8072",
1805
- sandybrown: "f4a460",
1806
- seagreen: "2e8b57",
1807
- seashell: "fff5ee",
1808
- sienna: "a0522d",
1809
- silver: "c0c0c0",
1810
- skyblue: "87ceeb",
1811
- slateblue: "6a5acd",
1812
- slategray: "708090",
1813
- slategrey: "708090",
1814
- snow: "fffafa",
1815
- springgreen: "00ff7f",
1816
- steelblue: "4682b4",
1817
- tan: "d2b48c",
1818
- teal: "008080",
1819
- thistle: "d8bfd8",
1820
- tomato: "ff6347",
1821
- turquoise: "40e0d0",
1822
- violet: "ee82ee",
1823
- wheat: "f5deb3",
1824
- white: "fff",
1825
- whitesmoke: "f5f5f5",
1826
- yellow: "ff0",
1827
- yellowgreen: "9acd32"
1875
+ while (results--) {
1876
+ ret.push(tinycolor({ h: h, s: s, v: v}));
1877
+ v = (v + modification) % 1;
1878
+ }
1879
+
1880
+ return ret;
1881
+ }
1882
+
1883
+ // Utility Functions
1884
+ // ---------------------
1885
+
1886
+ tinycolor.mix = function(color1, color2, amount) {
1887
+ amount = (amount === 0) ? 0 : (amount || 50);
1888
+
1889
+ var rgb1 = tinycolor(color1).toRgb();
1890
+ var rgb2 = tinycolor(color2).toRgb();
1891
+
1892
+ var p = amount / 100;
1893
+ var w = p * 2 - 1;
1894
+ var a = rgb2.a - rgb1.a;
1895
+
1896
+ var w1;
1897
+
1898
+ if (w * a == -1) {
1899
+ w1 = w;
1900
+ } else {
1901
+ w1 = (w + a) / (1 + w * a);
1902
+ }
1903
+
1904
+ w1 = (w1 + 1) / 2;
1905
+
1906
+ var w2 = 1 - w1;
1907
+
1908
+ var rgba = {
1909
+ r: rgb2.r * w1 + rgb1.r * w2,
1910
+ g: rgb2.g * w1 + rgb1.g * w2,
1911
+ b: rgb2.b * w1 + rgb1.b * w2,
1912
+ a: rgb2.a * p + rgb1.a * (1 - p)
1828
1913
  };
1829
1914
 
1830
- // Make it easy to access colors via `hexNames[hex]`
1831
- var hexNames = tinycolor.hexNames = flip(names);
1915
+ return tinycolor(rgba);
1916
+ };
1917
+
1832
1918
 
1919
+ // Readability Functions
1920
+ // ---------------------
1921
+ // <http://www.w3.org/TR/AERT#color-contrast>
1922
+
1923
+ // `readability`
1924
+ // Analyze the 2 colors and returns an object with the following properties:
1925
+ // `brightness`: difference in brightness between the two colors
1926
+ // `color`: difference in color/hue between the two colors
1927
+ tinycolor.readability = function(color1, color2) {
1928
+ var c1 = tinycolor(color1);
1929
+ var c2 = tinycolor(color2);
1930
+ var rgb1 = c1.toRgb();
1931
+ var rgb2 = c2.toRgb();
1932
+ var brightnessA = c1.getBrightness();
1933
+ var brightnessB = c2.getBrightness();
1934
+ var colorDiff = (
1935
+ Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
1936
+ Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
1937
+ Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
1938
+ );
1939
+
1940
+ return {
1941
+ brightness: Math.abs(brightnessA - brightnessB),
1942
+ color: colorDiff
1943
+ };
1944
+ };
1833
1945
 
1834
- // Utilities
1835
- // ---------
1946
+ // `readable`
1947
+ // http://www.w3.org/TR/AERT#color-contrast
1948
+ // Ensure that foreground and background color combinations provide sufficient contrast.
1949
+ // *Example*
1950
+ // tinycolor.isReadable("#000", "#111") => false
1951
+ tinycolor.isReadable = function(color1, color2) {
1952
+ var readability = tinycolor.readability(color1, color2);
1953
+ return readability.brightness > 125 && readability.color > 500;
1954
+ };
1836
1955
 
1837
- // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
1838
- function flip(o) {
1839
- var flipped = { };
1840
- for (var i in o) {
1841
- if (o.hasOwnProperty(i)) {
1842
- flipped[o[i]] = i;
1843
- }
1956
+ // `mostReadable`
1957
+ // Given a base color and a list of possible foreground or background
1958
+ // colors for that base, returns the most readable color.
1959
+ // *Example*
1960
+ // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1961
+ tinycolor.mostReadable = function(baseColor, colorList) {
1962
+ var bestColor = null;
1963
+ var bestScore = 0;
1964
+ var bestIsReadable = false;
1965
+ for (var i=0; i < colorList.length; i++) {
1966
+
1967
+ // We normalize both around the "acceptable" breaking point,
1968
+ // but rank brightness constrast higher than hue.
1969
+
1970
+ var readability = tinycolor.readability(baseColor, colorList[i]);
1971
+ var readable = readability.brightness > 125 && readability.color > 500;
1972
+ var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1973
+
1974
+ if ((readable && ! bestIsReadable) ||
1975
+ (readable && bestIsReadable && score > bestScore) ||
1976
+ ((! readable) && (! bestIsReadable) && score > bestScore)) {
1977
+ bestIsReadable = readable;
1978
+ bestScore = score;
1979
+ bestColor = tinycolor(colorList[i]);
1844
1980
  }
1845
- return flipped;
1846
1981
  }
1982
+ return bestColor;
1983
+ };
1847
1984
 
1848
- // Return a valid alpha value [0,1] with all invalid values being set to 1
1849
- function boundAlpha(a) {
1850
- a = parseFloat(a);
1851
1985
 
1852
- if (isNaN(a) || a < 0 || a > 1) {
1853
- a = 1;
1854
- }
1986
+ // Big List of Colors
1987
+ // ------------------
1988
+ // <http://www.w3.org/TR/css3-color/#svg-color>
1989
+ var names = tinycolor.names = {
1990
+ aliceblue: "f0f8ff",
1991
+ antiquewhite: "faebd7",
1992
+ aqua: "0ff",
1993
+ aquamarine: "7fffd4",
1994
+ azure: "f0ffff",
1995
+ beige: "f5f5dc",
1996
+ bisque: "ffe4c4",
1997
+ black: "000",
1998
+ blanchedalmond: "ffebcd",
1999
+ blue: "00f",
2000
+ blueviolet: "8a2be2",
2001
+ brown: "a52a2a",
2002
+ burlywood: "deb887",
2003
+ burntsienna: "ea7e5d",
2004
+ cadetblue: "5f9ea0",
2005
+ chartreuse: "7fff00",
2006
+ chocolate: "d2691e",
2007
+ coral: "ff7f50",
2008
+ cornflowerblue: "6495ed",
2009
+ cornsilk: "fff8dc",
2010
+ crimson: "dc143c",
2011
+ cyan: "0ff",
2012
+ darkblue: "00008b",
2013
+ darkcyan: "008b8b",
2014
+ darkgoldenrod: "b8860b",
2015
+ darkgray: "a9a9a9",
2016
+ darkgreen: "006400",
2017
+ darkgrey: "a9a9a9",
2018
+ darkkhaki: "bdb76b",
2019
+ darkmagenta: "8b008b",
2020
+ darkolivegreen: "556b2f",
2021
+ darkorange: "ff8c00",
2022
+ darkorchid: "9932cc",
2023
+ darkred: "8b0000",
2024
+ darksalmon: "e9967a",
2025
+ darkseagreen: "8fbc8f",
2026
+ darkslateblue: "483d8b",
2027
+ darkslategray: "2f4f4f",
2028
+ darkslategrey: "2f4f4f",
2029
+ darkturquoise: "00ced1",
2030
+ darkviolet: "9400d3",
2031
+ deeppink: "ff1493",
2032
+ deepskyblue: "00bfff",
2033
+ dimgray: "696969",
2034
+ dimgrey: "696969",
2035
+ dodgerblue: "1e90ff",
2036
+ firebrick: "b22222",
2037
+ floralwhite: "fffaf0",
2038
+ forestgreen: "228b22",
2039
+ fuchsia: "f0f",
2040
+ gainsboro: "dcdcdc",
2041
+ ghostwhite: "f8f8ff",
2042
+ gold: "ffd700",
2043
+ goldenrod: "daa520",
2044
+ gray: "808080",
2045
+ green: "008000",
2046
+ greenyellow: "adff2f",
2047
+ grey: "808080",
2048
+ honeydew: "f0fff0",
2049
+ hotpink: "ff69b4",
2050
+ indianred: "cd5c5c",
2051
+ indigo: "4b0082",
2052
+ ivory: "fffff0",
2053
+ khaki: "f0e68c",
2054
+ lavender: "e6e6fa",
2055
+ lavenderblush: "fff0f5",
2056
+ lawngreen: "7cfc00",
2057
+ lemonchiffon: "fffacd",
2058
+ lightblue: "add8e6",
2059
+ lightcoral: "f08080",
2060
+ lightcyan: "e0ffff",
2061
+ lightgoldenrodyellow: "fafad2",
2062
+ lightgray: "d3d3d3",
2063
+ lightgreen: "90ee90",
2064
+ lightgrey: "d3d3d3",
2065
+ lightpink: "ffb6c1",
2066
+ lightsalmon: "ffa07a",
2067
+ lightseagreen: "20b2aa",
2068
+ lightskyblue: "87cefa",
2069
+ lightslategray: "789",
2070
+ lightslategrey: "789",
2071
+ lightsteelblue: "b0c4de",
2072
+ lightyellow: "ffffe0",
2073
+ lime: "0f0",
2074
+ limegreen: "32cd32",
2075
+ linen: "faf0e6",
2076
+ magenta: "f0f",
2077
+ maroon: "800000",
2078
+ mediumaquamarine: "66cdaa",
2079
+ mediumblue: "0000cd",
2080
+ mediumorchid: "ba55d3",
2081
+ mediumpurple: "9370db",
2082
+ mediumseagreen: "3cb371",
2083
+ mediumslateblue: "7b68ee",
2084
+ mediumspringgreen: "00fa9a",
2085
+ mediumturquoise: "48d1cc",
2086
+ mediumvioletred: "c71585",
2087
+ midnightblue: "191970",
2088
+ mintcream: "f5fffa",
2089
+ mistyrose: "ffe4e1",
2090
+ moccasin: "ffe4b5",
2091
+ navajowhite: "ffdead",
2092
+ navy: "000080",
2093
+ oldlace: "fdf5e6",
2094
+ olive: "808000",
2095
+ olivedrab: "6b8e23",
2096
+ orange: "ffa500",
2097
+ orangered: "ff4500",
2098
+ orchid: "da70d6",
2099
+ palegoldenrod: "eee8aa",
2100
+ palegreen: "98fb98",
2101
+ paleturquoise: "afeeee",
2102
+ palevioletred: "db7093",
2103
+ papayawhip: "ffefd5",
2104
+ peachpuff: "ffdab9",
2105
+ peru: "cd853f",
2106
+ pink: "ffc0cb",
2107
+ plum: "dda0dd",
2108
+ powderblue: "b0e0e6",
2109
+ purple: "800080",
2110
+ rebeccapurple: "663399",
2111
+ red: "f00",
2112
+ rosybrown: "bc8f8f",
2113
+ royalblue: "4169e1",
2114
+ saddlebrown: "8b4513",
2115
+ salmon: "fa8072",
2116
+ sandybrown: "f4a460",
2117
+ seagreen: "2e8b57",
2118
+ seashell: "fff5ee",
2119
+ sienna: "a0522d",
2120
+ silver: "c0c0c0",
2121
+ skyblue: "87ceeb",
2122
+ slateblue: "6a5acd",
2123
+ slategray: "708090",
2124
+ slategrey: "708090",
2125
+ snow: "fffafa",
2126
+ springgreen: "00ff7f",
2127
+ steelblue: "4682b4",
2128
+ tan: "d2b48c",
2129
+ teal: "008080",
2130
+ thistle: "d8bfd8",
2131
+ tomato: "ff6347",
2132
+ turquoise: "40e0d0",
2133
+ violet: "ee82ee",
2134
+ wheat: "f5deb3",
2135
+ white: "fff",
2136
+ whitesmoke: "f5f5f5",
2137
+ yellow: "ff0",
2138
+ yellowgreen: "9acd32"
2139
+ };
1855
2140
 
1856
- return a;
1857
- }
2141
+ // Make it easy to access colors via `hexNames[hex]`
2142
+ var hexNames = tinycolor.hexNames = flip(names);
1858
2143
 
1859
- // Take input from [0, n] and return it as [0, 1]
1860
- function bound01(n, max) {
1861
- if (isOnePointZero(n)) { n = "100%"; }
1862
2144
 
1863
- var processPercent = isPercentage(n);
1864
- n = mathMin(max, mathMax(0, parseFloat(n)));
2145
+ // Utilities
2146
+ // ---------
1865
2147
 
1866
- // Automatically convert percentage into number
1867
- if (processPercent) {
1868
- n = parseInt(n * max, 10) / 100;
2148
+ // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
2149
+ function flip(o) {
2150
+ var flipped = { };
2151
+ for (var i in o) {
2152
+ if (o.hasOwnProperty(i)) {
2153
+ flipped[o[i]] = i;
1869
2154
  }
2155
+ }
2156
+ return flipped;
2157
+ }
1870
2158
 
1871
- // Handle floating point rounding errors
1872
- if ((math.abs(n - max) < 0.000001)) {
1873
- return 1;
1874
- }
2159
+ // Return a valid alpha value [0,1] with all invalid values being set to 1
2160
+ function boundAlpha(a) {
2161
+ a = parseFloat(a);
1875
2162
 
1876
- // Convert into [0, 1] range if it isn't already
1877
- return (n % max) / parseFloat(max);
2163
+ if (isNaN(a) || a < 0 || a > 1) {
2164
+ a = 1;
1878
2165
  }
1879
2166
 
1880
- // Force a number between 0 and 1
1881
- function clamp01(val) {
1882
- return mathMin(1, mathMax(0, val));
1883
- }
2167
+ return a;
2168
+ }
1884
2169
 
1885
- // Parse an integer into hex
1886
- function parseHex(val) {
1887
- return parseInt(val, 16);
1888
- }
2170
+ // Take input from [0, n] and return it as [0, 1]
2171
+ function bound01(n, max) {
2172
+ if (isOnePointZero(n)) { n = "100%"; }
1889
2173
 
1890
- // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
1891
- // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
1892
- function isOnePointZero(n) {
1893
- return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
1894
- }
2174
+ var processPercent = isPercentage(n);
2175
+ n = mathMin(max, mathMax(0, parseFloat(n)));
1895
2176
 
1896
- // Check to see if string passed in is a percentage
1897
- function isPercentage(n) {
1898
- return typeof n === "string" && n.indexOf('%') != -1;
2177
+ // Automatically convert percentage into number
2178
+ if (processPercent) {
2179
+ n = parseInt(n * max, 10) / 100;
1899
2180
  }
1900
2181
 
1901
- // Force a hex value to have 2 characters
1902
- function pad2(c) {
1903
- return c.length == 1 ? '0' + c : '' + c;
2182
+ // Handle floating point rounding errors
2183
+ if ((math.abs(n - max) < 0.000001)) {
2184
+ return 1;
1904
2185
  }
1905
2186
 
1906
- // Replace a decimal with it's percentage value
1907
- function convertToPercentage(n) {
1908
- if (n <= 1) {
1909
- n = (n * 100) + "%";
1910
- }
2187
+ // Convert into [0, 1] range if it isn't already
2188
+ return (n % max) / parseFloat(max);
2189
+ }
1911
2190
 
1912
- return n;
1913
- }
2191
+ // Force a number between 0 and 1
2192
+ function clamp01(val) {
2193
+ return mathMin(1, mathMax(0, val));
2194
+ }
1914
2195
 
1915
- var matchers = (function() {
2196
+ // Parse a base-16 hex value into a base-10 integer
2197
+ function parseIntFromHex(val) {
2198
+ return parseInt(val, 16);
2199
+ }
1916
2200
 
1917
- // <http://www.w3.org/TR/css3-values/#integers>
1918
- var CSS_INTEGER = "[-\\+]?\\d+%?";
2201
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
2202
+ // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
2203
+ function isOnePointZero(n) {
2204
+ return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
2205
+ }
1919
2206
 
1920
- // <http://www.w3.org/TR/css3-values/#number-value>
1921
- var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2207
+ // Check to see if string passed in is a percentage
2208
+ function isPercentage(n) {
2209
+ return typeof n === "string" && n.indexOf('%') != -1;
2210
+ }
1922
2211
 
1923
- // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
1924
- var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2212
+ // Force a hex value to have 2 characters
2213
+ function pad2(c) {
2214
+ return c.length == 1 ? '0' + c : '' + c;
2215
+ }
1925
2216
 
1926
- // Actual matching.
1927
- // Parentheses and commas are optional, but not required.
1928
- // Whitespace can take the place of commas or opening paren
1929
- var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
1930
- var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2217
+ // Replace a decimal with it's percentage value
2218
+ function convertToPercentage(n) {
2219
+ if (n <= 1) {
2220
+ n = (n * 100) + "%";
2221
+ }
1931
2222
 
1932
- return {
1933
- rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
1934
- rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
1935
- hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
1936
- hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
1937
- hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
1938
- hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
1939
- hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
1940
- };
1941
- })();
2223
+ return n;
2224
+ }
1942
2225
 
1943
- // `stringInputToObject`
1944
- // Permissive string parsing. Take in a number of formats, and output an object
1945
- // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
1946
- function stringInputToObject(color) {
2226
+ // Converts a decimal to a hex value
2227
+ function convertDecimalToHex(d) {
2228
+ return Math.round(parseFloat(d) * 255).toString(16);
2229
+ }
2230
+ // Converts a hex value to a decimal
2231
+ function convertHexToDecimal(h) {
2232
+ return (parseIntFromHex(h) / 255);
2233
+ }
1947
2234
 
1948
- color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
1949
- var named = false;
1950
- if (names[color]) {
1951
- color = names[color];
1952
- named = true;
1953
- }
1954
- else if (color == 'transparent') {
1955
- return { r: 0, g: 0, b: 0, a: 0, format: "name" };
1956
- }
2235
+ var matchers = (function() {
2236
+
2237
+ // <http://www.w3.org/TR/css3-values/#integers>
2238
+ var CSS_INTEGER = "[-\\+]?\\d+%?";
2239
+
2240
+ // <http://www.w3.org/TR/css3-values/#number-value>
2241
+ var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2242
+
2243
+ // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
2244
+ var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2245
+
2246
+ // Actual matching.
2247
+ // Parentheses and commas are optional, but not required.
2248
+ // Whitespace can take the place of commas or opening paren
2249
+ var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2250
+ var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2251
+
2252
+ return {
2253
+ rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2254
+ rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2255
+ hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2256
+ hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2257
+ hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2258
+ hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
2259
+ hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2260
+ hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2261
+ hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
2262
+ };
2263
+ })();
1957
2264
 
1958
- // Try to match string input using regular expressions.
1959
- // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
1960
- // Just return an object and let the conversion functions handle that.
1961
- // This way the result will be the same whether the tinycolor is initialized with string or object.
1962
- var match;
1963
- if ((match = matchers.rgb.exec(color))) {
1964
- return { r: match[1], g: match[2], b: match[3] };
1965
- }
1966
- if ((match = matchers.rgba.exec(color))) {
1967
- return { r: match[1], g: match[2], b: match[3], a: match[4] };
1968
- }
1969
- if ((match = matchers.hsl.exec(color))) {
1970
- return { h: match[1], s: match[2], l: match[3] };
1971
- }
1972
- if ((match = matchers.hsla.exec(color))) {
1973
- return { h: match[1], s: match[2], l: match[3], a: match[4] };
1974
- }
1975
- if ((match = matchers.hsv.exec(color))) {
1976
- return { h: match[1], s: match[2], v: match[3] };
1977
- }
1978
- if ((match = matchers.hex6.exec(color))) {
1979
- return {
1980
- r: parseHex(match[1]),
1981
- g: parseHex(match[2]),
1982
- b: parseHex(match[3]),
1983
- format: named ? "name" : "hex"
1984
- };
1985
- }
1986
- if ((match = matchers.hex3.exec(color))) {
1987
- return {
1988
- r: parseHex(match[1] + '' + match[1]),
1989
- g: parseHex(match[2] + '' + match[2]),
1990
- b: parseHex(match[3] + '' + match[3]),
1991
- format: named ? "name" : "hex"
1992
- };
1993
- }
2265
+ // `stringInputToObject`
2266
+ // Permissive string parsing. Take in a number of formats, and output an object
2267
+ // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2268
+ function stringInputToObject(color) {
2269
+
2270
+ color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
2271
+ var named = false;
2272
+ if (names[color]) {
2273
+ color = names[color];
2274
+ named = true;
2275
+ }
2276
+ else if (color == 'transparent') {
2277
+ return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2278
+ }
1994
2279
 
1995
- return false;
2280
+ // Try to match string input using regular expressions.
2281
+ // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2282
+ // Just return an object and let the conversion functions handle that.
2283
+ // This way the result will be the same whether the tinycolor is initialized with string or object.
2284
+ var match;
2285
+ if ((match = matchers.rgb.exec(color))) {
2286
+ return { r: match[1], g: match[2], b: match[3] };
2287
+ }
2288
+ if ((match = matchers.rgba.exec(color))) {
2289
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
2290
+ }
2291
+ if ((match = matchers.hsl.exec(color))) {
2292
+ return { h: match[1], s: match[2], l: match[3] };
2293
+ }
2294
+ if ((match = matchers.hsla.exec(color))) {
2295
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
2296
+ }
2297
+ if ((match = matchers.hsv.exec(color))) {
2298
+ return { h: match[1], s: match[2], v: match[3] };
2299
+ }
2300
+ if ((match = matchers.hsva.exec(color))) {
2301
+ return { h: match[1], s: match[2], v: match[3], a: match[4] };
2302
+ }
2303
+ if ((match = matchers.hex8.exec(color))) {
2304
+ return {
2305
+ a: convertHexToDecimal(match[1]),
2306
+ r: parseIntFromHex(match[2]),
2307
+ g: parseIntFromHex(match[3]),
2308
+ b: parseIntFromHex(match[4]),
2309
+ format: named ? "name" : "hex8"
2310
+ };
2311
+ }
2312
+ if ((match = matchers.hex6.exec(color))) {
2313
+ return {
2314
+ r: parseIntFromHex(match[1]),
2315
+ g: parseIntFromHex(match[2]),
2316
+ b: parseIntFromHex(match[3]),
2317
+ format: named ? "name" : "hex"
2318
+ };
2319
+ }
2320
+ if ((match = matchers.hex3.exec(color))) {
2321
+ return {
2322
+ r: parseIntFromHex(match[1] + '' + match[1]),
2323
+ g: parseIntFromHex(match[2] + '' + match[2]),
2324
+ b: parseIntFromHex(match[3] + '' + match[3]),
2325
+ format: named ? "name" : "hex"
2326
+ };
1996
2327
  }
1997
2328
 
1998
- // Expose tinycolor to window, does not need to run in non-browser context.
1999
- window.tinycolor = tinycolor;
2329
+ return false;
2330
+ }
2000
2331
 
2332
+ window.tinycolor = tinycolor;
2001
2333
  })();
2002
2334
 
2003
-
2004
2335
  $(function () {
2005
2336
  if ($.fn.spectrum.load) {
2006
2337
  $.fn.spectrum.processNativeColorInputs();
2007
2338
  }
2008
2339
  });
2009
2340
 
2010
- })(window, jQuery);
2341
+ });