404 lines
11 KiB
JavaScript
Executable File
404 lines
11 KiB
JavaScript
Executable File
|
|
// A nutty little DHTML Color Picker
|
|
// By Martin Atkins aka Mart
|
|
|
|
var colpic_imgprefix = '/img';
|
|
|
|
// spawnPicker - create a picker window
|
|
function spawnPicker(dataobject, displayobject, des) {
|
|
var p = window.open("","colorpick_"+dataobject.name,"width=560,height=450");
|
|
var d = p.document;
|
|
|
|
// declare the data storage object in the picker's scope
|
|
d.write('<script language="JavaScript"> var picker = new Object; </script>');
|
|
|
|
var dat = p.picker;
|
|
dat.dataobject = dataobject;
|
|
dat.displayobject = displayobject;
|
|
dat.current = ''+dataobject.value;
|
|
dat.r = 0;
|
|
dat.g = 0;
|
|
dat.b = 0;
|
|
dat.h = 0;
|
|
dat.s = 0;
|
|
dat.v = 0;
|
|
|
|
// Copy some functions into the picker's scope so events can hit them
|
|
p._HSVtoRGB = _HSVtoRGB;
|
|
p._varstoform = _varstoform;
|
|
p.setBGColor = setBGColor;
|
|
p.findel = findel;
|
|
|
|
d.write("<title>"+des+"</title>");
|
|
_createInterface(p);
|
|
d.close();
|
|
|
|
findel('spectrum',d).onclick=function(evt) {
|
|
if (! evt) { evt = p.event; }
|
|
var x, y;
|
|
if (evt.offsetX != null) {
|
|
x = evt.offsetX;
|
|
y = evt.offsetY;
|
|
} else if (evt.pageX != null) {
|
|
x = evt.pageX - 6;
|
|
y = evt.pageY - 6;
|
|
} else if (evt.clientX != null) {
|
|
x = evt.clientX - 6;
|
|
y = evt.clientY - 6;
|
|
} else {
|
|
p.alert('Your mouseclick could not be handled. Sorry.');
|
|
}
|
|
// var x = evt.offsetX || (evt.pageX ? evt.pageX - 6 : false) || (evt.clientX - 6);
|
|
// var y = evt.offsetY || (evt.pageY ? evt.pageX - 6 : false) || (evt.clientY - 6);
|
|
p.picker.h = Math.abs(p.Math.floor(x / 2) % 256);
|
|
p.picker.s = Math.abs(y % 255);
|
|
p._HSVtoRGB(p);
|
|
p._varstoform(p);
|
|
};
|
|
findel('brightness',d).onclick=function(evt) {
|
|
if (! evt) { evt = p.event; }
|
|
p.picker.v = Math.abs((evt.offsetY || (evt.pageY - 6)) % 255);
|
|
p._HSVtoRGB(p);
|
|
p._varstoform(p);
|
|
};
|
|
|
|
findel('btnCancel',d).onclick=function() {
|
|
p.close();
|
|
};
|
|
|
|
findel('btnOK',d).onclick=function() {
|
|
dataobject.value=p.picker.current;
|
|
p.setBGColor(displayobject,p.picker.current);
|
|
p.close();
|
|
};
|
|
|
|
// The crosshair prevents clicks under it, so fake events for it
|
|
findel('crosshair',d).onclick=function(evt) {
|
|
if (! evt) { evt = p.event; }
|
|
var fakeevt = new Object;
|
|
fakeevt.pageX = evt.pageX;
|
|
fakeevt.pageY = evt.pageY;
|
|
fakeevt.clientX = evt.clientX;
|
|
fakeevt.clientY = evt.clientY;
|
|
findel('spectrum',p.document).onclick(fakeevt);
|
|
};
|
|
|
|
findel('fr',d).onchange=
|
|
findel('fg',d).onchange=
|
|
findel('fb',d).onchange=function() {
|
|
dat.r = Math.abs(findel('fr',d).value % 256);
|
|
dat.g = Math.abs(findel('fg',d).value % 256);
|
|
dat.b = Math.abs(findel('fb',d).value % 256);
|
|
|
|
_RGBtoHSV(p);
|
|
_varstoform(p);
|
|
}
|
|
|
|
findel('fh',d).onchange=
|
|
findel('fs',d).onchange=
|
|
findel('fv',d).onchange=function() {
|
|
dat.h = Math.abs(findel('fh',d).value % 255);
|
|
dat.s = Math.abs(findel('fs',d).value % 256);
|
|
dat.v = Math.abs(findel('fv',d).value % 256);
|
|
|
|
_HSVtoRGB(p);
|
|
_varstoform(p);
|
|
}
|
|
|
|
_setcolor(p,dat.current);
|
|
|
|
return false;
|
|
}
|
|
|
|
function setBGColor(displayobject, colorstring) {
|
|
displayobject.style.backgroundColor = colorstring;
|
|
}
|
|
|
|
function findel(id,doc) {
|
|
if (! doc) {
|
|
doc = document;
|
|
}
|
|
return doc.getElementById(id);
|
|
}
|
|
|
|
function _varstoform(p) {
|
|
var d = p.document;
|
|
var dat = p.picker;
|
|
findel("fr",d).value=dat.r;
|
|
findel("fg",d).value=dat.g;
|
|
findel("fb",d).value=dat.b;
|
|
findel("fh",d).value=dat.h;
|
|
findel("fs",d).value=dat.s;
|
|
findel("fv",d).value=dat.v;
|
|
|
|
dat.current = "#"+_hex(dat.r)+
|
|
_hex(dat.g)+
|
|
_hex(dat.b);
|
|
setBGColor(findel('preview',p.document),dat.current);
|
|
|
|
_updatebrightnessgrad(p);
|
|
_placeindicators(p);
|
|
}
|
|
|
|
function _updatebrightnessgrad(p) {
|
|
var grad = findel("brightness",p.document);
|
|
var fbc = new Object;
|
|
fbc.h=p.picker.h;
|
|
fbc.s=p.picker.s;
|
|
fbc.v=255;
|
|
_HSVtoRGB(p,fbc);
|
|
gradclr = _hex(fbc.r)+
|
|
_hex(fbc.g)+
|
|
_hex(fbc.b);
|
|
var newgradurl = "/palimg/colorpicker/longgrad.gif/pg00000000ff"+gradclr.toLowerCase();
|
|
var oldgradurl = grad.src;
|
|
if (oldgradurl != newgradurl) {
|
|
grad.src = newgradurl;
|
|
}
|
|
}
|
|
function _placeindicators(p) {
|
|
var d = p.document;
|
|
var pointer = findel('pointer',d);
|
|
var crosshair = findel('crosshair',d);
|
|
pointer.style.top = (p.picker.v + 3)+"px";
|
|
|
|
crosshair.style.top = (p.picker.s - 1)+"px";
|
|
crosshair.style.left = ((p.picker.h * 2) - 1)+"px";
|
|
|
|
pointer.style.display = '';
|
|
crosshair.style.display = '';
|
|
}
|
|
|
|
function _setcolor(p,htmlcolor) {
|
|
p.picker.current = htmlcolor;
|
|
|
|
var clrparts = _colorfromstring(htmlcolor);
|
|
|
|
p.picker.r = clrparts[1];
|
|
p.picker.g = clrparts[2];
|
|
p.picker.b = clrparts[3];
|
|
|
|
_RGBtoHSV(p);
|
|
_varstoform(p);
|
|
|
|
}
|
|
|
|
function _RGBtoHSV(p,dat) {
|
|
if (! dat) {
|
|
dat = p.picker;
|
|
}
|
|
var r = dat.r;
|
|
var g = dat.g;
|
|
var b = dat.b;
|
|
|
|
r = (r % 256) / 255;
|
|
g = (g % 256) / 255;
|
|
b = (b % 256) / 255;
|
|
|
|
var min = 255, max = 0, h, s, v, hi, diff;
|
|
|
|
var rgb = new Array(0,r,g,b);
|
|
for (var i = 1; i <= 3; i++) {
|
|
if (rgb[i] > max) {
|
|
max = rgb[i];
|
|
hi = 1;
|
|
}
|
|
if (rgb[i] < min) {
|
|
min = rgb[i];
|
|
}
|
|
}
|
|
diff = max - min;
|
|
v = max;
|
|
if (max == 0) {
|
|
s = 0;
|
|
} else {
|
|
s = diff / max;
|
|
}
|
|
if (s == 0) {
|
|
h = 0;
|
|
} else {
|
|
switch (hi) {
|
|
case 1:
|
|
h = (g - b) / diff;
|
|
break;
|
|
case 2:
|
|
h = 2 + (b - r) / diff;
|
|
break;
|
|
case 3:
|
|
h = 4 + (r - g) / diff;
|
|
break;
|
|
}
|
|
h = h / 6;
|
|
if (h < 0) {
|
|
h = h + 1;
|
|
}
|
|
}
|
|
dat.h = Math.floor(h * 255);
|
|
dat.s = Math.floor(s * 255);
|
|
dat.v = Math.floor(v * 255);
|
|
}
|
|
function _HSVtoRGB(p,dat) {
|
|
if (! dat) {
|
|
dat = p.picker;
|
|
}
|
|
|
|
var h = dat.h;
|
|
var s = dat.s;
|
|
var v = dat.v;
|
|
|
|
// If value is zero, return black.
|
|
if (v == 0) {
|
|
dat.r =
|
|
dat.g =
|
|
dat.b = 0;
|
|
return;
|
|
}
|
|
|
|
// If there's no saturation, return a grey.
|
|
if (s == 0) {
|
|
dat.r =
|
|
dat.g =
|
|
dat.b = v;
|
|
return;
|
|
}
|
|
|
|
h = (h % 255) / 255;
|
|
s = (s % 256) / 255;
|
|
v = (v % 256) / 255;
|
|
|
|
var t, aa, bb, cc, r, g, b;
|
|
|
|
t = p.Math.floor(h * 6); // Find which color's range we're in.
|
|
f = (h * 6) - t;
|
|
aa = v * (1 - s);
|
|
bb = v * (1 - s * f);
|
|
cc = v * (1 - (s * (1 - f)));
|
|
|
|
switch (t) {
|
|
case 0:
|
|
r=v;
|
|
g=cc;
|
|
b=aa;
|
|
break;
|
|
case 1:
|
|
r=bb;
|
|
g=v;
|
|
b=aa;
|
|
break;
|
|
case 2:
|
|
r=aa;
|
|
g=v;
|
|
b=cc;
|
|
break;
|
|
case 3:
|
|
r=aa;
|
|
g=bb;
|
|
b=v;
|
|
break;
|
|
case 4:
|
|
r=cc;
|
|
g=aa;
|
|
b=v;
|
|
break;
|
|
default:
|
|
r=v;
|
|
g=aa;
|
|
b=bb;
|
|
break;
|
|
}
|
|
|
|
dat.r = p.Math.floor(r * 255) % 256;
|
|
dat.g = p.Math.floor(g * 255) % 256;
|
|
dat.b = p.Math.floor(b * 255) % 256;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Fun with Regular Expressions
|
|
function _colorfromstring(strcolor) {
|
|
var clrparts;
|
|
strcolor = strcolor.toLowerCase();
|
|
if ((clrparts = strcolor.match(
|
|
/^#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/
|
|
)) != null) {
|
|
for (var i=1; i<=3; i++) {
|
|
clrparts[i] = parseInt(clrparts[i],16);
|
|
}
|
|
return clrparts;
|
|
} else if ((clrparts = strcolor.match(
|
|
/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/
|
|
)) != null) {
|
|
for (var i=1; i<=3; i++) {
|
|
if (clrparts[i]<0 || clrparts[i]>255) {
|
|
return [0,0,0,0];
|
|
}
|
|
return clrparts;
|
|
}
|
|
}
|
|
return [0,255,255,255];
|
|
}
|
|
|
|
function _hex(i) {
|
|
var r = '';
|
|
var h = new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
|
|
|
|
for (var x = 0; x < 32; x++) {
|
|
if (Math.pow( 16, x + 1 ) > i)
|
|
break;
|
|
}
|
|
|
|
for ( var y = x; y >= 0; y-- ) {
|
|
var z = Math.pow( 16, y );
|
|
r += h[ Math.floor ( i / z ) ];
|
|
i = i % z;
|
|
}
|
|
|
|
r = ( r.length == 0 ) ? '0' : r;
|
|
while ( r.length < 2 ) {
|
|
r = '0' + r;
|
|
}
|
|
return r
|
|
}
|
|
|
|
function _createInterface(p) {
|
|
var curclr = p.picker.current;
|
|
var d = p.document;
|
|
d.write('<style type="text/css">\n'+
|
|
'body { border: 0; padding: 0; margin: 0; background: ButtonFace; color: ButtonText; font: caption; }\n'+
|
|
'button { width: 5em; margin: 5px;}\n'+
|
|
'img { border: 1px solid #000000; padding: 0; margin: 0; }\n'+
|
|
'</style>');
|
|
d.write('<table cellspacing="5" cellpadding="0" border="0">\n');
|
|
d.write('<tr><td><img src="' + colpic_imgprefix + '/colorpicker/spectrum.png" '+
|
|
'ismap width="512" height="256" id="spectrum"></td>\n');
|
|
d.write('<td><img src="/palimg/colorpicker/longgrad.gif" '+
|
|
'ismap width="25" height="256" id="brightness"></td></tr></table>\n');
|
|
d.write('<form action="about:blank" method="GET" onsubmit="return false;">\n');
|
|
d.write('<center><table cellspacing="5" cellpadding="0" border="0" width="95%">\n');
|
|
d.write('<tr><td rowspan="3"><div id="preview" style="background-color: '+curclr+'; '+
|
|
'border: 1px solid #000000; width: 50px; height: 50px; margin-left: 25%;"> </div></td>\n');
|
|
_writeControlRow(d,'Hue','fh');
|
|
_writeControlRow(d,'Red','fr');
|
|
d.write('</tr><tr>\n');
|
|
_writeControlRow(d,'Saturation','fs');
|
|
_writeControlRow(d,'Green','fg');
|
|
d.write('</tr><tr>\n');
|
|
_writeControlRow(d,'Lightness','fv');
|
|
_writeControlRow(d,'Blue','fb');
|
|
d.write('</tr></table></center>\n');
|
|
d.write('<div style="text-align: center;">'+
|
|
'<button id="btnOK">OK</button> <button id="btnCancel">Cancel</button>'+
|
|
'</div>');
|
|
d.write('</form>\n');
|
|
d.write('<img style="position: absolute; display: none; border: 0; left: 0; top: 0;" id="crosshair" src="' + colpic_imgprefix + '/colorpicker/crosshair.gif">\n');
|
|
d.write('<img style="position: absolute; display: none; border: 0; left: 552px; top: 0;" id="pointer" src="' + colpic_imgprefix + '/colorpicker/pointer.gif">\n');
|
|
}
|
|
function _writeControlRow(doc,caption,name) {
|
|
doc.write('<td align="right" width="25%"><nobr><label accesskey="'+caption.substring(0,1)+'">'+caption+
|
|
': <input type="text" size="3" maxlength="3" name="'+name+'" id="'+name+'"></label></nobr></td>\n');
|
|
}
|
|
|
|
function colPic_set_imgprefix(prefix) {
|
|
colpic_imgprefix = prefix;
|
|
} |