
/* Javascript code module for quirks mode */

/*
======================================================

** ZippyPalette **
Shipscript's Rainbow Color Module.
Image-based HSL version. 05 Aug 2008
Loosely following the MS Paint model.
This palette version has been designed 
to display correctly in QUIRKS mode.
copyright 2008 www.isdntek.com

====================================================
<!-- insert palette in page: -->
buildPalette(width,height)
----------------------------------------------------
<!-- example input from application to module: -->
<input id="incolor" type="text" value="" 
onkeyup="if (event.keyCode==13){sendColor(this.value)}"
><input type="button" value="set" 
onclick="sendColor(this.previousSibling.value)">
----------------------------------------------------
<!-- example output from module to application: -->
function setColor(palettecolor){document.bgColor=palettecolor}
====================================================
Note: a background image behind the tool will cause
sluggishness in IE6
*/

/* location of module and size of palette */
var imgbase="include/"
var fx=3, fy=6;  /*180x192*/

//fx=4; fy=8;
//fx=2; fy=3;
//fx=5; fy=5;
//fx=3, fy=4;

/* ====================================================== */

var colorW=60,colorH=32;
var rainbowX, rainbowY;
var fnt

var xhOS=200; /*offset - marker is 400x400*/
var hueX,hueY;
var movX,movY;
var cmove=false;

var vsOS=-6;   /*slider value offset*/
var vbarOS=6; /*crossbar is 32x12*/
//var vbarOS=40  /*slider is 11x80*/
var sliderleft=0
var lumY,slideY;
var smove=false;

var isIE=document.all;

function buildPalette(w,h){
  if (w>0) {fx=w}
  if (h>0) {fy=h}

  rainbowX=colorW*fx;
  rainbowY=colorH*fy;
  //fnt=4*fx;
  //fnt=Math.ceil((rainbowX+32)*.07) ;
  fnt=(rainbowX+32)*.07 ;
  var rainbowstyle=
  '\n<style type="text/css">'+
  '\n .palette   	{ position:relative; width:'+Math.ceil(rainbowX+2*fnt+32)+'px; height:'+Math.ceil(rainbowY+(fnt*3))+'px; }'+
  '\n .colorvals	{ position:relative; z-index:1;}'+
  '\n span#showHex,span#showDec { position:relative; display:block; float:left; width:'+Math.round((rainbowX+1*fnt+32)*.4)+'px; height:'+(fnt*2)+'px;  left:'+fnt+'px; top:'+Math.round(fnt*.5)+'px; '+
  				' font-family:verdana; font-size:'+Math.ceil(fnt)+'px; line-height:'+Math.round(fnt*1.2)+'px; font-weight:bold; }'+
  '\n span#showDec   	   { width:'+Math.round((rainbowX+1*fnt+32)*.6)+'px;  }'+
  '\n .colorzone 	{ position:relative; width:'+Math.round(rainbowX+1.5*fnt)+'px; height:'+(rainbowY+fnt)+'px; float:left; clear:both; }'+
  '\n .rainbow   	{ position:relative; width:'+rainbowX+'px; height:'+rainbowY+'px; left:'+fnt+'px; }'+
  '\n .rainbow img	{ width:'+rainbowX+'px; height:'+rainbowY+'px; }'+
  '\n .crosshair 	{ position:absolute; left:0px; top:0px; width:'+rainbowX+'px; height:'+rainbowY+'px;  background:transparent url('+imgbase+'targetCrosshair.gif) no-repeat ; } '+
  '\n .slidezone { position:relative; z-index:2; width:32px; top:-'+(2*vbarOS)+'px; height:'+(rainbowY+3*vbarOS)+'px; float:left; background:transparent url('+imgbase+'vslidemark.gif) 0 0 no-repeat ;}'+
  '\n .luminance { position:relative; width:14px; height:'+rainbowY+'px; left:9px; top:'+(2*vbarOS)+'; overflow:hidden; background-color:transparent;}'+
  '\n</style>';


  var rainbowpalette=
  '<div id="palette" class="palette" onmouseup="endMove()">'+
  '  <div class="colorvals"><span id="showHex" > </span><span id="showDec" title="ZippyPalette @ from Shipscript"> </span></div>'+
  '  <div id="colorzone" class="colorzone" align="left" >'+
  ' 	<div class="rainbow">'+
  '	  <img src="'+imgbase+'paintrainbow_60x32_basis.jpg">'+
  '	  <div class="crosshair" id="crosshair"  onmousedown="startxhair(event)" '+
  '	  onmousemove="movexhair(event)" onmouseup="endMove()" ondrag="return false"></div>'+
  '	</div>'+
  '  </div>'+
  '  <div id="slidezone" align="left" class="slidezone" onmousedown="startslide(event)" onmousemove="moveslide(event)" onmouseup="endMove()" ondrag="return false">'+
  '	<div id="luminance" class="luminance" >'+
  '	<span style="width:16px; height:'+(rainbowY)+'px; '+
  '	    filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+ imgbase+ 'LumVal.png\', sizingMethod=\'scale\')"'+
  '	    ><img src="'+ imgbase+ 'LumVal.png" onselect="return false" ondrag="return false" onmousedown="return false"'+
  '	    style="width:16px; height:'+(rainbowY)+'px; '+
  '	    filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);"'+
  '     ></span>'+   /*image or scale*/
  '	</div>' +
  '  </div>'+
  '</div>';

  document.write(rainbowstyle);
  document.write(rainbowpalette);

  initPalette();
  setxhair();
}

var palettenamedcolors=new Array(
"#F0F8FF","Aliceblue",
"#FAEBD7","Antiquewhite",
"#00FFFF","Aqua",
"#7FFFD4","Aquamarine",
"#F0FFFF","Azure",
"#F5F5DC","Beige",
"#FFE4C4","Bisque",
"#000000","Black",
"#FFEBCD","Blanchedalmond",
"#0000FF","Blue",
"#8A2BE2","Blueviolet",
"#A52A2A","Brown",
"#DEB887","Burlywood",
"#5F9EA0","Cadetblue",
"#7FFF00","Chartreuse",
"#D2691E","Chocolate",
"#FF7F50","Coral",
"#6495ED","Cornflowerblue",
"#FFF8DC","Cornsilk",
"#DC143C","Crimson",
"#00FFFF","Cyan",
"#00008B","Darkblue",
"#008B8B","Darkcyan",
"#B8860B","Darkgoldenrod",
"#A9A9A9","Darkgray",
"#006400","Darkgreen",
"#BDB76B","Darkkhaki",
"#8B008B","Darkmagenta",
"#556B2F","Darkolivegreen",
"#FF8C00","Darkorange",
"#9932CC","Darkorchid",
"#8B0000","Darkred",
"#E9967A","Darksalmon",
"#8FBC8F","Darkseagreen",
"#483D8B","Darkslateblue",
"#2F4F4F","Darkslategray",
"#00CED1","Darkturquoise",
"#9400D3","Darkviolet",
"#FF1493","Deeppink",
"#00BFFF","Deepskyblue",
"#696969","Dimgray",
"#1E90FF","Dodgerblue",
"#B22222","Firebrick",
"#FFFAF0","Floralwhite",
"#228B22","Forestgreen",
"#FF00FF","Fuchsia",
"#DCDCDC","Gainsboro",
"#F8F8FF","Ghostwhite",
"#FFD700","Gold",
"#DAA520","Goldenrod",
"#808080","Gray",
"#008000","Green",
"#ADFF2F","Greenyellow",
"#F0FFF0","Honeydew",
"#FF69B4","Hotpink",
"#CD5C5C","Indianred",
"#4B0082","Indigo",
"#FFFFF0","Ivory",
"#F0E68C","Khaki",
"#E6E6FA","Lavender",
"#FFF0F5","Lavenderblush",
"#7CFC00","Lawngreen",
"#FFFACD","Lemonchiffon",
"#ADD8E6","Lightblue",
"#F08080","Lightcoral",
"#E0FFFF","Lightcyan",
"#FAFAD2","Lightgoldenrodyellow",
"#90EE90","Lightgreen",
"#D3D3D3","Lightgrey",
"#FFB6C1","Lightpink",
"#FFA07A","Lightsalmon",
"#20B2AA","Lightseagreen",
"#87CEFA","Lightskyblue",
"#778899","Lightslategray",
"#B0C4DE","Lightsteelblue",
"#FFFFE0","Lightyellow",
"#00FF00","Lime",
"#32CD32","Limegreen",
"#FAF0E6","Linen",
"#FF00FF","Magenta",
"#800000","Maroon",
"#66CDAA","Mediumauqamarine",
"#0000CD","Mediumblue",
"#BA55D3","Mediumorchid",
"#9370D8","Mediumpurple",
"#3CB371","Mediumseagreen",
"#7B68EE","Mediumslateblue",
"#00FA9A","Mediumspringgreen",
"#48D1CC","Mediumturquoise",
"#C71585","Mediumvioletred",
"#191970","Midnightblue",
"#F5FFFA","Mintcream",
"#FFE4E1","Mistyrose",
"#FFE4B5","Moccasin",
"#FFDEAD","Navajowhite",
"#000080","Navy",
"#FDF5E6","Oldlace",
"#808000","Olive",
"#688E23","Olivedrab",
"#FFA500","Orange",
"#FF4500","Orangered",
"#DA70D6","Orchid",
"#EEE8AA","Palegoldenrod",
"#98FB98","Palegreen",
"#AFEEEE","Paleturquoise",
"#D87093","Palevioletred",
"#FFEFD5","Papayawhip",
"#FFDAB9","Peachpuff",
"#CD853F","Peru",
"#FFC0CB","Pink",
"#DDA0DD","Plum",
"#B0E0E6","Powderblue",
"#800080","Purple",
"#FF0000","Red",
"#BC8F8F","Rosybrown",
"#4169E1","Royalblue",
"#8B4513","Saddlebrown",
"#FA8072","Salmon",
"#F4A460","Sandybrown",
"#2E8B57","Seagreen",
"#FFF5EE","Seashell",
"#A0522D","Sienna",
"#C0C0C0","Silver",
"#87CEEB","Skyblue",
"#6A5ACD","Slateblue",
"#708090","Slategray",
"#FFFAFA","Snow",
"#00FF7F","Springgreen",
"#4682B4","Steelblue",
"#D2B48C","Tan",
"#008080","Teal",
"#D8BFD8","Thistle",
"#FF6347","Tomato",
"#40E0D0","Turquoise",
"#EE82EE","Violet",
"#F5DEB3","Wheat",
"#FFFFFF","White",
"#F5F5F5","Whitesmoke",
"#FFFF00","Yellow",
"#9ACD32","YellowGreen"
);

function fromcolorname(cname){ //--converts named internet colors to hex values from the table
	for (var c=0; c<palettenamedcolors.length; c++){
	  if (palettenamedcolors[c].toUpperCase()==cname.toUpperCase()&& cname.indexOf("#")<0){
	    cname=(palettenamedcolors[c-1]);
	  }
	}
	return cname; /* return the hex #value*/
}

function tocolorname(cname){ //--converts hex values to named colors from the table
	for (var c=0; c<palettenamedcolors.length; c++){
	  if (palettenamedcolors[c].toUpperCase()==cname.toUpperCase()&& cname.indexOf("#")>-1){
	    cname=(palettenamedcolors[c+1]);
	  }
	}
	return cname; /* return the color name*/
}




function $(v){ return document.getElementById(v)}

function initPalette(){ 
	/* predefine positions to make values available */
	$('crosshair').style.backgroundPosition=(rainbowX/2-xhOS)+" "+(rainbowY/2-xhOS);
	$('slidezone').style.backgroundPosition=sliderleft+"px "+(rainbowY/2-vsOS)+"px";
}


function startxhair(e){
	cmove=true;
	hueX=parseInt($('crosshair').style.backgroundPosition.split(" ")[0]);
	hueY=parseInt($('crosshair').style.backgroundPosition.split(" ")[1]);
   	movX=isIE ? event.clientX : e.clientX;
    	movY=isIE ? event.clientY : e.clientY;

}

function movexhair(e){
	if (cmove==false){return}
	//puActiveItem=isIE ? event.srcElement : e.target; 
    	var dotX=isIE ? event.clientX : e.clientX;
    	var dotY=isIE ? event.clientY : e.clientY;
	dotX=dotX-movX+hueX;
	dotY=dotY-movY+hueY;
	$('crosshair').style.backgroundPosition=dotX+"px "+dotY+"px";
	setxhair();
}

function setxhair(){
	var bsX=parseInt($('crosshair').style.backgroundPosition.split(" ")[0])+xhOS;
	var bsY=parseInt($('crosshair').style.backgroundPosition.split(" ")[1])+xhOS;
	bsX=Math.round(Math.min(Math.max(0,bsX),rainbowX)); /* set limits */
	bsY=Math.round(Math.min(Math.max(0,bsY),rainbowY));
	$('crosshair').style.backgroundPosition=(bsX-xhOS)+"px "+(bsY-xhOS)+"px";
	var hexv=hsl2rgb(bsX/rainbowX, 1-bsY/rainbowY, 0.5);
	$('luminance').style.backgroundColor="rgb("+hexv+")";
	var lmY=parseInt($('slidezone').style.backgroundPosition.split(" ")[1])+vsOS;
	var hexv=hsl2rgb(bsX/rainbowX, 1-bsY/rainbowY, 1-lmY/rainbowY);
	$('palette').style.backgroundColor="rgb("+hexv+")";
	$('showHex').innerHTML="#"+rgb2hex(hexv);
	$('showHex').style.color=makeOppColor(hexv);
	$('showDec').innerHTML="("+hexv+")";
	$('showDec').style.color=makeOppColor(hexv);
	UserAppDynaColor("#"+rgb2hex(hexv));
}


function startslide(e){
	smove=true;
	lumY=parseInt($('slidezone').style.backgroundPosition.split(" ")[1]);
    	slideY=isIE ? event.clientY : e.clientY;

}
function moveslide(e){
	if (smove==false){return}
    	var barY=isIE ? event.clientY : e.clientY;
	var barY=barY-slideY+lumY;
	$('slidezone').style.backgroundPosition=sliderleft+"px "+barY+"px";
	setslide();
}
function setslide(){
	var bsX=parseInt($('crosshair').style.backgroundPosition.split(" ")[0])+xhOS;
	var bsY=parseInt($('crosshair').style.backgroundPosition.split(" ")[1])+xhOS;
	var lmY=parseInt($('slidezone').style.backgroundPosition.split(" ")[1])+vsOS;
	var lmY=Math.round(Math.min(Math.max(0,lmY),rainbowY)); /* set limits */
	$('slidezone').style.backgroundPosition=sliderleft+"px "+(lmY-vsOS)+"px";
	var hexv=hsl2rgb(bsX/rainbowX, 1-bsY/rainbowY, 1-lmY/rainbowY);
	$('palette').style.backgroundColor="rgb("+hexv+")";
	$('showHex').innerHTML="#"+rgb2hex(hexv);
	$('showHex').style.color=makeOppColor(hexv);
	$('showDec').innerHTML="("+hexv+")";
	$('showDec').style.color=makeOppColor(hexv);
	UserAppDynaColor("#"+rgb2hex(hexv));

}

function endMove(){
	if (cmove==true){setxhair();}
	if (smove==true){setslide();}
	UserAppSetColor($('showHex').innerHTML);
	cmove=false;
	smove=false;
}


function makeAppColor(incolor){  /* display color from user application */
	var RGB=getRGB(incolor); /* test color format and return array*/
	var HSL=rgb2hsl(RGB);  	 /* returns array to position palette markers */
	$('crosshair').style.backgroundPosition=(HSL[0]*rainbowX-xhOS)+" "+((1-HSL[1])*rainbowY-xhOS);
	$('slidezone').style.backgroundPosition="0 "+((1-HSL[2])*rainbowY-vsOS);
	var lum=hsl2rgb(HSL[0], HSL[1], 0.5);
	$('luminance').style.backgroundColor="rgb("+lum+")";
	$('palette').style.backgroundColor="rgb("+RGB+")";
	$('showHex').innerHTML="#"+rgb2hex(RGB);
	$('showHex').style.color=makeOppColor(RGB);
	$('showDec').innerHTML="("+RGB+")";
	$('showDec').style.color=makeOppColor(RGB);
	UserAppSetColor("#"+rgb2hex(RGB));
}


//==============================================
// Interfaces to application
//==============================================

function sendColor(newcolor) { /* Interface to application */
	//--receive color from application or keyboard and send to palette
	//  non-color values will convert to white.
	makeAppColor(newcolor);
}

function UserAppDynaColor(val){
	// if user has function in application, send value.
	try { setDynaColor(val) }
	catch(e) { return(false)}
}

function UserAppSetColor(val){
	// if user has function in application, send value.
	try { setColor(val) }
	catch(e) { return(false)}
}

//==============================================
// Conversions
//==============================================

function makeOppColor(C){
	// Black or white contrasting text colors 
	// R+G+B=440 seems to be a good midpoint
	if ( (parseInt(C[0])+parseInt(C[1])+parseInt(C[2]))<440 )  {oppColor="#FFFFFF"}else{oppColor="#000000";}
	return oppColor;
}

function getRGB(oldcolor){
	// convert a color in another HTML format to a hex value
	var RGB=new Array();
	var hexlist="0123456789ABCDEF";
	// remove various accidental punctuation that user might send
	oldcolor=oldcolor.replace(/\s+/g,"").toUpperCase() ;				
	oldcolor=oldcolor.replace(/'/g,"") ;				
	oldcolor=oldcolor.replace(/"/g,"") ;				
	oldcolor=oldcolor.replace(/;/g,"") ;				
	oldcolor=oldcolor.replace(/=/g,"") ;				
	oldcolor=oldcolor.replace(/:/g,"") ;				
	oldcolor=oldcolor.replace(/>/g,"") ;				
	oldcolor=oldcolor.replace(/</g,"") ;
	if (oldcolor.match(/RGB/i) || oldcolor.match(/,/i)){			
		oldcolor=oldcolor.replace(/(RGB)/gi,"");
		oldcolor=oldcolor.replace(/[\(\)]/gi,"");
		if (oldcolor.match(/[^0-9,]/)){RGB=[255,255,255]}
		else{RGB=oldcolor.split(",");}
	}
	else 
	{
	    if (oldcolor.match(/[^0123456789ABCDEF#]/i)){
		oldcolor=fromcolorname(oldcolor);
	    }
	    if ( !oldcolor.match(/[^0123456789ABCDEF#]/i)  ){
		// if all characters are valid for a color
		oldcolor=oldcolor.replace(/#/g,""); 
		if (oldcolor.length==3){for (var j=0;j<3; j++){
			RGB[j]=(hexlist.indexOf(oldcolor.charAt(j))*16)+hexlist.indexOf(oldcolor.charAt(j)); }
		}else {for (var j=0;j<3; j++){
			RGB[j]=(hexlist.indexOf(oldcolor.charAt(j*2))*16)+hexlist.indexOf(oldcolor.charAt(j*2+1)); }
		}
	    } 
	    else { // a problem, so just assume white
		RGB=[255,255,255]
	    }

	}
	return RGB // three fielded decimal values
}

function rgb2hex(RGB)   { return(byte2hex(RGB[0])+byte2hex(RGB[1])+byte2hex(RGB[2])); /* builds hex value without #*/}
function byte2hex(d)    { d=Math.round(Math.min(Math.max(0,d),255)); return("0123456789ABCDEF".charAt((d-d%16)/16)+"0123456789ABCDEF".charAt(d%16)); }




//==============================================
//HSL to RGB  *  http://www.easyrgb.com/math.php
//==============================================
// Hue (x) Saturation (y) Luminance (z)

function hsl2rgb(H,S,L){
	var R,G,B	
	if ( S==0 ) {             	//HSL values = 0 to 1
	   R = Math.floor(L*255);	//RGB results = 0 to 255
	   G = Math.floor(L*255);
	   B = Math.floor(L*255);
	}
	else {
	   if (L<0.5) {var_2 = L*(1+S)}
	   else       {var_2 = (L+S)-(S*L)}
	   var_1 = 2*L-var_2;

	   R = Math.floor(255 * hue2rgb( var_1, var_2, H+(1/3) ));
	   G = Math.floor(255 * hue2rgb( var_1, var_2, H ));
	   B = Math.floor(255 * hue2rgb( var_1, var_2, H-(1/3) ));
	}
	return [R,G,B];
}

function hue2rgb( v1, v2, vH ) {	//Function Hue to RGB
	   if ( vH<0 ) {vH+=1}
	   if ( vH>1 ) {vH-=1}
	   if ( (6*vH)<1 ) {return ( v1 + (v2-v1)*6*vH ) }
	   if ( (2*vH)<1 ) {return ( v2 )}
	   if ( (3*vH)<2 ) {return ( v1 + (v2-v1)*((2/3)-vH )*6) }
	   return ( v1 );
}


//==============================================
//RGB to HSL  *  http://www.easyrgb.com/math.php?
//==============================================
function rgb2hsl(RGB){
	var R=RGB[0]/256; var G=RGB[1]/256; var B=RGB[2]/256;
	var H, S, L;
	var Min=Math.min(Math.min(R,G),B) ;
	var Max=Math.max(Math.max(R,G),B) ;
   	var Del=Max-Min ;
	L=(Max+Min)/2 ;

	if (Del==0){H=0; S=0 } /* grayscale */
	else {
	    if (L<0.5){S=Del/(Max+Min)}
	    else {S=Del/(2-Max-Min)}  		

	    var dR=( ((Max-R)/6)+(Del/2) )/Del;	
	    var dG=( ((Max-G)/6)+(Del/2) )/Del;	
	    var dB=( ((Max-B)/6)+(Del/2) )/Del;	

	    if      (R==Max){ H=dB-dG }
	    else if (G==Max){ H=(1/3)+dR-dB }
	    else if (B==Max){ H=(2/3)+dG-dR }
	    if (H<0){H+=1};
	    if (H>1){H-=1};
	}
	return [H,S,L];
}





//==============================================
//   these user functions go in application
//==============================================
/*

//----
// application functions to receive palette values
//----

	// palettecolor will be a 6-digit hex #value.
	// User inputs of improperly formatted color codes will
	// be converted to the color white (#FFFFFF). 

function setColor(palettecolor) { 
	// This function should be in the application to receive colors.
   	// This value arrives when the user clicks the Apply button
	// or when mouseup sets the palette color.
	if (palettecolor!=''){ document.bgColor=palettecolor }
}

function setDynaColor(palettecolor){
	// This optional function may be added to the application.
	// When the user clicks a color or holds down 
	// the mouse button while dragging over the palette, 
	// the colors will arrive here.  The application may 
	// use these values or the activity can be ignored by 
	// not writing any code for this function.
	if (palettecolor!=''){ document.bgColor=(palettecolor) }
}

//----
// application function-calls to set palette values
//----

//-- pass color up from application software or keyboard input
//-- can be 3 or 6-digit #hex value,  RGB(fielded) value, or color name.
//-- this function will also invoke the setColor function with the palette results.
sendColor(color)


//-- create the color table in the application.
//   set values as necessary or omit all values for default.
buildPalette(width,height);

*/

//==============================================


/* end */
