Today, we are going to take a look at how to create an interactive color picker using javascript, css, and html. There are a number of color picker packages out there on the web, but there isn't nearly as much on how to write one yourself and the mechanics behind how it works. Hopefully, after reading this article, you would be able to go off and write one yourself.
This tutorial builds on a number of other javascript articles on this site, including Javascript Objects - A Useful Example (which covers some basics about how objects work in javascript - and we will be using the color object created in that tutorial), Javascript - Working With Events (which covers how to work with events and event objects), and Javascript - Draggable Elements (which covers how to do dragging in javascript). So, if you are relatively new to javascript, I would suggest at least skimming those before you continue.
Below, you can see the result of what we will create today. You can adjust the hue by dragging the arrows on the color bar, and can adjust saturation and value by dragging around the small circle in the gradient square. The hex, RGB, and HSV values are output in the textboxes on the right, as well as a div containing the color picked. You can also enter values in the hex, RGB and HSV text boxes, and the correct color will show up (and the arrows and circle will move to the correct position). What we are going to create today is not a package, but it could be made into one very easily. Play around a bit - I know you want to.
| Hex: | |
| Red: | |
| Green: | |
| Blue: | |
| Hue: | |
| Saturation: | |
| Value: |
Ok, now that you've had your fun, lets dive right in. Right below, we have the html required to create the color picker:
<div id="gradientBox" style="cursor:crosshair;top:15px;position:absolute;
left:15px;width:256px;height:256px;">
<img id="gradientImg" style="display:block;width:256px;height:256px;"
src="/Color_Picker/color_picker_gradient.png" />
<img id="circle" style="position:absolute;height:11px;width:11px;"
src="/Color_Picker/color_picker_circle.gif" />
</div>
<div id="hueBarDiv" style="position:absolute;left:310px;width:35px;
height:256px;top:15px;">
<img style="position:absolute;height:256px; width:19px;left:8px;"
src="/Color_Picker/color_picker_bar.png" />
<img id="arrows" style="position:absolute;height:9px;width:35px;left:0px;"
src="/Color_Picker/color_picker_arrows.gif" />
</div>
<div style="position:absolute;left:370px;width:145px;height:256px;top:15px;">
<div style="position:absolute;border: 1px solid black;
height:50px;width:145px;top:0px;left:0px;">
<div id="quickColor" style="position:absolute;height:50px;width:73px;
top:0px;left:0px;">
</div>
<div id="staticColor" style="position:absolute;height:50px;width:72px;
top:0px;left:73px;">
</div>
</div>
<br />
<table width="100%" style="position:absolute;top:55px;">
<tr>
<td>Hex: </td>
<td>
<input size="8" type="text" id="hexBox" onchange="hexBoxChanged();" />
</td>
</tr>
<tr>
<td>Red: </td>
<td>
<input size="8" type="text" id="redBox" onchange="redBoxChanged();" />
</td>
</tr>
<tr>
<td>Green: </td>
<td>
<input size="8" type="text" id="greenBox" onchange="greenBoxChanged();" />
</td>
</tr>
<tr>
<td>Blue: </td>
<td>
<input size="8" type="text" id="blueBox" onchange="blueBoxChanged();" />
</td>
</tr>
<tr>
<td>Hue: </td>
<td>
<input size="8" type="text" id="hueBox" onchange="hueBoxChanged();" />
</td>
</tr>
<tr>
<td>Saturation: </td>
<td>
<input size="8" type="text" id="saturationBox"
onchange="saturationBoxChanged();" />
</td>
</tr>
<tr>
<td>Value: </td>
<td>
<input size="8" type="text" id="valueBox" onchange="valueBoxChanged();" />
</td>
</tr>
</table>
</div>
</div>
The stuff in the bottom half is really simple - it is just a table for the text boxes and their labels. Of course, each of them has a javascript function attached to their onchange event - but we will go into what those function do later. For now, we want to take a look at the top part - the divs that define the gradient box and the hue bar. The gradient box is just a div with a 256x256 partially transparent image inside of it. This partially transparent image is what gives the gradient - the upper right corner is completely transparent, the bottom right is solid white, and the left is solid black. Setting the background color on this div creates the appearance of a saturation-value gradient in that background color. This div also contains the circle image that represents the selected point.
The hue bar doesn't require any gradient tricks - it is just a standard hue bar, where the bottom is a hue of 0 and the top is a hue of 359. The arrows are a single image sitting on top of the bar, where the center of the arrow image is transparent. The other divs represent the color box on the upper right of the color picker - it is split into two divs, one which represents the current color that you are dragging over (quickColor), and the other represents the last color that you picked (staticColor). When you finish a drag operation - either on the gradient or the bar - both divs will update to show the color that the drag operation completed on.
So now that you have an idea of what is where in terms of the html elements, lets turn to the javascript. Below, we have the initialization code for the color picker:
var currentColor = Colors.ColorFromRGB(64,128,128);
new dragObject("arrows", "hueBarDiv", arrowsLowBounds, arrowsUpBounds,
arrowsDown, arrowsMoved, endMovement);
new dragObject("circle", "gradientBox", circleLowBounds, circleUpBounds,
circleDown, circleMoved, endMovement);
colorChanged('box');
Obviously, not much of that makes sense at the moment, but we shall take a look one line at a time. The first line, the call to fixGradientImage, is what makes this color picker work in Internet Explorer 6. IE6, as you probably know, does not support transparency on pngs by default - and so we have to apply this hack to get the gradient image to appear correctly. The function looks like the following:
{
fixPNG(document.getElementById("gradientImg"));
}
function fixPNG(myImage)
{
if(!document.body.filters)
return;
var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);
if(version < 5.5 || version >= 7)
return;
var imgID = (myImage.id) ? "id='" + myImage.id + "' " : ""
var imgStyle = "display:inline-block;" + myImage.style.cssText
var strNewHTML = "<span " + imgID + " style=\"width:" + myImage.width
+ "px; height:" + myImage.height + "px;" + imgStyle + ";"
+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
+ "(src=\'" + myImage.src + "\', sizingMethod='scale');\"></span>"
myImage.outerHTML = strNewHTML
}
There is plenty of info on the web about what exactly this hack does in IE6, so I won't go over that here. Suffice it to say, where we had a opaque image, we now have a span with a partially transparent png.
The next line of initialization code (var currentColor = Colors.ColorFromRGB(64,128,128);) sets up the global object that will always hold the currently selected color, and initializes it to a value smack dab in the middle of the spectrum. This is probably a good time to re-introduce the color object from Javascript Objects - A Useful Example. And here it is in all its glory:
{
this.ColorFromHSV = function(hue, sat, val)
{
var color = new Color();
color.SetHSV(hue,sat,val);
return color;
}
this.ColorFromRGB = function(r, g, b)
{
var color = new Color();
color.SetRGB(r,g,b);
return color;
}
this.ColorFromHex = function(hexStr)
{
var color = new Color();
color.SetHexString(hexStr);
return color;
}
function Color()
{
//Stored as values between 0 and 1
var red = 0;
var green = 0;
var blue = 0;
//Stored as values between 0 and 360
var hue = 0;
//Strored as values between 0 and 1
var saturation = 0;
var value = 0;
this.SetRGB = function(r, g, b)
{
if (isNaN(r) || isNaN(g) || isNaN(b))
return false;
r = r/255.0;
red = r > 1 ? 1 : r < 0 ? 0 : r;
g = g/255.0;
green = g > 1 ? 1 : g < 0 ? 0 : g;
b = b/255.0;
blue = b > 1 ? 1 : b < 0 ? 0 : b;
calculateHSV();
return true;
}
this.Red = function()
{ return Math.round(red*255); }
this.Green = function()
{ return Math.round(green*255); }
this.Blue = function()
{ return Math.round(blue*255); }
this.SetHSV = function(h, s, v)
{
if (isNaN(h) || isNaN(s) || isNaN(v))
return false;
hue = (h >= 360) ? 359.99 : (h < 0) ? 0 : h;
saturation = (s > 1) ? 1 : (s < 0) ? 0 : s;
value = (v > 1) ? 1 : (v < 0) ? 0 : v;
calculateRGB();
return true;
}
this.Hue = function()
{ return hue; }
this.Saturation = function()
{ return saturation; }
this.Value = function()
{ return value; }
this.SetHexString = function(hexString)
{
if(hexString == null || typeof(hexString) != "string")
return false;
if (hexString.substr(0, 1) == '#')
hexString = hexString.substr(1);
if(hexString.length != 6)
return false;
var r = parseInt(hexString.substr(0, 2), 16);
var g = parseInt(hexString.substr(2, 2), 16);
var b = parseInt(hexString.substr(4, 2), 16);
return this.SetRGB(r,g,b);
}
this.HexString = function()
{
var rStr = this.Red().toString(16);
if (rStr.length == 1)
rStr = '0' + rStr;
var gStr = this.Green().toString(16);
if (gStr.length == 1)
gStr = '0' + gStr;
var bStr = this.Blue().toString(16);
if (bStr.length == 1)
bStr = '0' + bStr;
return ('#' + rStr + gStr + bStr).toUpperCase();
}
this.Complement = function()
{
var newHue = (hue>= 180) ? hue - 180 : hue + 180;
var newVal = (value * (saturation - 1) + 1);
var newSat = (value*saturation) / newVal;
var newColor = new Color();
newColor.SetHSV(newHue, newSat, newVal);
return newColor;
}
function calculateHSV()
{
var max = Math.max(Math.max(red, green), blue);
var min = Math.min(Math.min(red, green), blue);
value = max;
saturation = 0;
if(max != 0)
saturation = 1 - min/max;
hue = 0;
if(min == max)
return;
var delta = (max - min);
if (red == max)
hue = (green - blue) / delta;
else if (green == max)
hue = 2 + ((blue - red) / delta);
else
hue = 4 + ((red - green) / delta);
hue = hue * 60;
if(hue <0)
hue += 360;
}
function calculateRGB()
{
red = value;
green = value;
blue = value;
if(value == 0 || saturation == 0)
return;
var tHue = (hue / 60);
var i = Math.floor(tHue);
var f = tHue - i;
var p = value * (1 - saturation);
var q = value * (1 - saturation * f);
var t = value * (1 - saturation * (1 - f));
switch(i)
{
case 0:
red = value; green = t; blue = p;
break;
case 1:
red = q; green = value; blue = p;
break;
case 2:
red = p; green = value; blue = t;
break;
case 3:
red = p; green = q; blue = value;
break;
case 4:
red = t; green = p; blue = value;
break;
default:
red = value; green = p; blue = q;
break;
}
}
}
}
();
This code, as explained in that previous tutorial, creates a static Colors object which can be used to create color objects (which can take RGB, HSV, or Hex and produce RGB, HSV, or Hex). I'm not going to go into detail on how it works here - if you want to know more about it, read the tutorial.
The next two lines in the initialization hook the two elements that need to be draggable - the circle and the arrows.
arrowsDown, arrowsMoved, endMovement);
new dragObject("circle", "gradientBox", circleLowBounds, circleUpBounds,
circleDown, circleMoved, endMovement);
The first line here declares that the element arrows is draggable and hueBarDiv is the handle. This means that if you click anywhere on the hueBarDiv, the arrows will start dragging. Then we give it a lower and an upper position bound for where we can drag the arrows, and three functions, a function to call at the beginning of dragging, one after each movement, and one when dragging completes. We set the same type of thing up in the second line, for the circle on the gradient image - but in this case the gradientBox is the drag handle - so if you click anywhere on the gradient image, you start dragging the circle.
Just as a refresher, here is the main chunk of code behind dragObj:
startCallback, moveCallback, endCallback, attachLater)
{
if(typeof(element) == "string")
element = document.getElementById(element);
if(element == null)
return;
if(lowerBound != null && upperBound != null)
{
var temp = lowerBound.Min(upperBound);
upperBound = lowerBound.Max(upperBound);
lowerBound = temp;
}
var cursorStartPos = null;
var elementStartPos = null;
var dragging = false;
var listening = false;
var disposed = false;
function dragStart(eventObj)
{
if(dragging || !listening || disposed)
return;
dragging = true;
if(startCallback != null)
startCallback(eventObj, element);
cursorStartPos = absoluteCursorPostion(eventObj);
elementStartPos = new Position(parseInt(element.style.left),
parseInt(element.style.top));
elementStartPos = elementStartPos.Check();
hookEvent(document, "mousemove", dragGo);
hookEvent(document, "mouseup", dragStopHook);
return cancelEvent(eventObj);
}
function dragGo(eventObj)
{
if(!dragging || disposed)
return;
var newPos = absoluteCursorPostion(eventObj);
newPos = newPos.Add(elementStartPos)
newPos = newPos.Subtract(cursorStartPos);
newPos = newPos.Bound(lowerBound, upperBound)
newPos.Apply(element);
if(moveCallback != null)
moveCallback(newPos, element);
return cancelEvent(eventObj);
}
function dragStopHook(eventObj)
{
dragStop();
return cancelEvent(eventObj);
}
function dragStop()
{
if(!dragging || disposed)
return;
unhookEvent(document, "mousemove", dragGo);
unhookEvent(document, "mouseup", dragStopHook);
cursorStartPos = null;
elementStartPos = null;
if(endCallback != null)
endCallback(element);
dragging = false;
}
this.Dispose = function()
{
if(disposed)
return;
this.StopListening(true);
element = null;
attachElement = null
lowerBound = null;
upperBound = null;
startCallback = null;
moveCallback = null
endCallback = null;
disposed = true;
}
this.StartListening = function()
{
if(listening || disposed)
return;
listening = true;
hookEvent(attachElement, "mousedown", dragStart);
}
this.StopListening = function(stopCurrentDragging)
{
if(!listening || disposed)
return;
unhookEvent(attachElement, "mousedown", dragStart);
listening = false;
if(stopCurrentDragging && dragging)
dragStop();
}
this.IsDragging = function(){ return dragging; }
this.IsListening = function() { return listening; }
this.IsDisposed = function() { return disposed; }
if(typeof(attachElement) == "string")
attachElement = document.getElementById(attachElement);
if(attachElement == null)
attachElement = element;
if(!attachLater)
this.StartListening();
}
This code is from the Javascript - Draggable Elements tutorial. Again, since there is a very detailed discussion of the draggable code in that tutorial, I'm just going to gloss right over it here.
So back to those drag object initializations - what are the upper and lower bounds of the arrows and the circle? They are position objects (and if you don't know what our position object is, go read the draggable elements tutorial again). And here is what they are defined as:
var arrowsUpBounds = new Position(0, 251);
var circleLowBounds = new Position(-5, -5);
var circleUpBounds = new Position(250, 250);
The fact that both the lower and the upper X value for the arrows is the same number means that it can't be dragged left or right, but only up or down. The reason the other numbers aren't quite what you might expect is that these positions represent the upper left corner of the circle/arrow elements. This means that they are offset by the half the width and half the height so that the center of the elements can reach the edge of its bounding area.
So those are the bounds - now what about the callbacks? Well, first we have the start callbacks - circleDown and arrowsDown. Lets see what they do:
{
var pos = getMousePos(e);
if(getEventTarget(e) == arrows)
pos.Y += parseInt(arrows.style.top);
pos = correctOffset(pos, arrowsOffset, true);
pos = pos.Bound(arrowsLowBounds, arrowsUpBounds);
pos.Apply(arrows);
arrowsMoved(pos);
}
function circleDown(e, circle)
{
var pos = getMousePos(e);
if(getEventTarget(e) == circle)
{
pos.X += parseInt(circle.style.left);
pos.Y += parseInt(circle.style.top);
}
pos = correctOffset(pos, circleOffset, true);
pos = pos.Bound(circleLowBounds, circleUpBounds);
pos.Apply(circle);
circleMoved(pos);
}
These two functions may be small but they accomplish a lot. Lets go over the arrowsDown one step by step. First we get the current mouse position from the event object. This is done with the following function:
{
eventObj = eventObj ? eventObj : window.event;
var pos;
if(isNaN(eventObj.layerX))
pos = new Position(eventObj.offsetX, eventObj.offsetY);
else
pos = new Position(eventObj.layerX, eventObj.layerY);
return correctOffset(pos, pointerOffset, true);
}
Here we get the correct event object (see Javascript - Working With Events for an explanation of why), and then we get the current mouse position, relative to the element that triggered the event. Of course, Internet Explorer and Firefox do this differently, so we have the two different ways of getting the number here. Once we have that position we call the function correctOffset, and get a new position back (which we then return). This correctOffset function is rather simplistic, but serves an important purpose:
{
if(neg)
return pos.Subtract(offset);
return pos.Add(offset);
}
All it does is take a position and an offset (both position objects), and either applies or unapplies that offset (according to the third argument). We use it in the getMousePos function with the pointerOffset:
var circleOffset = new Position(5, 5);
var arrowsOffset = new Position(0, 4);
For whatever horrible reason, where Firefox reports the tip of the pointer to be is not actually the tip of the pointer - it is 1 pixel off in the X direction. So, we need this pointer offset value. The other two offsets listed here are much more acceptable - they are the values to get from the upper left pixel of the circle/arrow to the center point value that we need (we will be using these two offsets a bunch later).
Ok, so back to the arrowsDown code. We now have the current mouse position relative to the element that triggered the event. The next thing we do is check what element triggered the event - and if it is the arrows themselves, we add the current position of the arrows (in the Y direction) to the Y mouse position. This way we now have the mouse position relative to the hue bar. The reason we don't do anything with the X position here is that the X position of the arrows never changes. Now we call correctOffset again, but this time it is to adjust for the height of the arrows image (i.e., we adjust it using the arrowsOffset). This is so that the current mouse position ends up at the center of the arrows image, instead of at the top. Now that we have what will become the new position for the arrows, we bound it to make sure it falls within the correct range (using the lower and upper arrow bounds). Then we apply the new position to the arrows element. Finally, we call the function arrowsMoved with the new position. What all this code essentially accomplishes is to move the arrows to the point at which you clicked on the hue bar. The code for circleDown accomplishes the exact same task, but for the circle on the gradient image.
Now on to the functions arrowsMoved and circleMoved. They are called at the end of their respective 'Down' functions, and they are also called after every movement during a drag. So lets see what they do:
{
pos = correctOffset(pos, arrowsOffset, false);
currentColor.SetHSV((256 - pos.Y)*359.99/255, currentColor.Saturation(),
currentColor.Value());
colorChanged("arrows");
}
function circleMoved(pos, element)
{
pos = correctOffset(pos, circleOffset, false);
currentColor.SetHSV(currentColor.Hue(), 1-pos.Y/255.0, pos.X/255.0);
colorChanged("circle");
}
Again, the two functions look extremely similar. They start by offsetting the position (the position passed in is the one for the new upper-left position of the element, so we are bringing it back to the center of the their respective elements). Next we set the new current color, based on the position. For the arrows, the Y position transforms into the hue - first we flip it (since in coordinate space, 0 is at the top, but in the space of the hue bar, 0 is at the bottom), and then we scale it from the range 0-255 (the range of the hue bar image) to the range 0-359.99 (the actual range of hue that we deal with). For the circle, the Y position becomes the saturation (where again, it is flipped) and we scale it from the range 0-255 to the range 0-1. The X position becomes the new value, and here we just scale it from 0-255 to 0-1. Finally, we call a function called colorChanged:
{
document.getElementById("hexBox").value = currentColor.HexString();
document.getElementById("redBox").value = currentColor.Red();
document.getElementById("greenBox").value = currentColor.Green();
document.getElementById("blueBox").value = currentColor.Blue();
document.getElementById("hueBox").value = Math.round(currentColor.Hue());
var str = (currentColor.Saturation()*100).toString();
if(str.length > 4)
str = str.substr(0,4);
document.getElementById("saturationBox").value = str;
str = (currentColor.Value()*100).toString();
if(str.length > 4)
str = str.substr(0,4);
document.getElementById("valueBox").value = str;
if(source == "arrows" || source == "box")
document.getElementById("gradientBox").style.backgroundColor=
Colors.ColorFromHSV(currentColor.Hue(), 1, 1).HexString();
if(source == "box")
{
var el = document.getElementById("arrows");
el.style.top = (256 - currentColor.Hue()*255/359.99 - arrowsOffset.Y) + 'px';
var pos = new Position(currentColor.Value()*255,
(1-currentColor.Saturation())*255);
pos = correctOffset(pos, circleOffset, true);
pos.Apply("circle");
endMovement();
}
document.getElementById("quickColor").style.backgroundColor =
currentColor.HexString();
}
This function is where we synchronize all the various elements of the color picker. The one argument, source is a string representing where the new values have come from. This string has three possible values - "arrows", "circle", and "box" - where "arrows" means the position of the arrows has changes, "circle" means the position of the circle has changed, and "box" means that one of the input boxes has changed.
So first in this function, we update the various text boxes - because these always need to be updated, no matter what changed. The saturation and value text boxes get multiplied up to be a percentage and then rounded to look nicer. If the source was the arrows or the box, we update the background color of the gradient div - whose color we get by taking the current hue and giving it a value and saturation of 1. If the source was a text box, we update the position of the arrows and the circle, from the current color. Essentially, we do the reverse of the calculation that we used to get from position to color. We also call a function endMovement in this case, which I will explain in a moment. Finally, we update the current color of the quickColor div to be the currently selected color.
So now we have the function endMovement, which is called after a drag operation completes on the arrows or circle, and is also called whenever a text box causes something to change. It is pretty simple, all it does is set the staticColor div to the new color:
{
document.getElementById("staticColor").style.backgroundColor =
currentColor.HexString();
}
We are actually almost done now! The final call in initialization was to call colorChanged('box');, which you understand now is to get all the color picker components synced with the initial color choice. There are only a couple more functions - and they are all extremely simple. They are the onchange functions for each of the text boxes:
{
currentColor.SetHexString(document.getElementById("hexBox").value);
colorChanged("box");
}
function redBoxChanged(e)
{
currentColor.SetRGB(parseInt(document.getElementById("redBox").value),
currentColor.Green(), currentColor.Blue());
colorChanged("box");
}
function greenBoxChanged(e)
{
currentColor.SetRGB(currentColor.Red(),
parseInt(document.getElementById("greenBox").value), currentColor.Blue());
colorChanged("box");
}
function blueBoxChanged(e)
{
currentColor.SetRGB(currentColor.Red(), currentColor.Green(),
parseInt(document.getElementById("blueBox").value));
colorChanged("box");
}
function hueBoxChanged(e)
{
currentColor.SetHSV(parseFloat(document.getElementById("hueBox").value),
currentColor.Saturation(), currentColor.Value());
colorChanged("box");
}
function saturationBoxChanged(e)
{
currentColor.SetHSV(currentColor.Hue(),
parseFloat(document.getElementById("saturationBox").value)/100.0,
currentColor.Value());
colorChanged("box");
}
function valueBoxChanged(e)
{
currentColor.SetHSV(currentColor.Hue(), currentColor.Saturation(),
parseFloat(document.getElementById("valueBox").value)/100.0);
colorChanged("box");
}
Each of those functions just takes the new value from its repective text box, pushes that new value into the current color object, and then calls colorChanged("box") in order to update everyone else.
And that covers it for how to make a color picker using javascript! Hope you enjoyed it, and if you would like the raw javascript code to play around with, feel free to download it here. The html and couple lines of initialization javascript are not in that file, but you can copy all that from the boxes above or the source of this page. As always, if you have any questions, please leave them in the comments.
08/24/2007 - 08:41
could you please give links to the .png and .gif files that are in your code?
08/24/2007 - 20:59
Sure! Here are all the links:
Gradient, Hue Bar, Arrows, Circle
12/09/2007 - 16:10
Is it possible, via javascript, to rotate the hue of an entire image, dynamicly? the ideal would be to provide a color pallete or a slider and according to the values(of the slider) that the user provides, the hue/saturation/brightness of the entire image, to change accordingly. if you know how to do so a tutorial would be just about great! :D
01/28/2008 - 14:01
I play with this code but the drag object did not work. Do I miss something?
05/27/2008 - 23:18
I second oasis' motion. The drag object is not working... Have I done something wrong?
05/28/2008 - 06:19
Perhaps you forgot to include the chunk on initialization javascript at the end. Here is what the full html code should look like:
<head>
<script src="javascript.js" type="text/javascript"></script>
</head>
<body>
<div style="position:relative;height:286px;
width:531px;border:1px solid black;">
<div id="gradientBox" style="cursor:crosshair;
top:15px;position:absolute;left:15px;
width:256px;height:256px;">
<img id="gradientImg"
style="display:block;width:256px;height:256px;"
src="/Color_Picker/color_picker_gradient.png" />
<img id="circle"
style="position:absolute;height:11px;
width:11px;"
src="/Color_Picker/color_picker_circle.gif" />
</div>
<div id="hueBarDiv" style="position:absolute;
left:310px;width:35px;
height:256px;top:15px;">
<img style="position:absolute;height:256px;
width:19px;left:8px;"
src="/Color_Picker/color_picker_bar.png" />
<img id="arrows" style="position:absolute;
height:9px;width:35px;left:0px;"
src="/Color_Picker/color_picker_arrows.gif" />
</div>
<div style="position:absolute;left:370px;
width:145px;
height:256px;top:15px;">
<div style="position:absolute;
border: 1px solid black;
height:50px;width:145px;top:0px;left:0px;">
<div id="quickColor" style="position:absolute;
height:50px;width:73px;top:0px;left:0px;">
</div>
<div id="staticColor" style="position:absolute;
height:50px;width:72px;top:0px;left:73px;">
</div>
</div>
<br />
<table width="100%"
style="position:absolute;top:55px;">
<tr>
<td>Hex: </td>
<td>
<input size="8" type="text" id="hexBox"
onchange="hexBoxChanged();" />
</td>
</tr>
<tr>
<td>Red: </td>
<td>
<input size="8" type="text" id="redBox"
onchange="redBoxChanged();" />
</td>
</tr>
<tr>
<td>Green: </td>
<td>
<input size="8" type="text" id="greenBox"
onchange="greenBoxChanged();" />
</td>
</tr>
<tr>
<td>Blue: </td>
<td>
<input size="8" type="text" id="blueBox"
onchange="blueBoxChanged();" />
</td>
</tr>
<tr>
<td>Hue: </td>
<td>
<input size="8" type="text" id="hueBox"
onchange="hueBoxChanged();" />
</td>
</tr>
<tr>
<td>Saturation: </td>
<td>
<input size="8" type="text"
id="saturationBox"
onchange="saturationBoxChanged();" />
</td>
</tr>
<tr>
<td>Value: </td>
<td>
<input size="8" type="text" id="valueBox"
onchange="valueBoxChanged();" />
</td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
fixGradientImg();
var currentColor = Colors.ColorFromRGB(64,128,128);
new dragObject("arrows", "hueBarDiv",
arrowsLowBounds, arrowsUpBounds,
arrowsDown, arrowsMoved, endMovement);
new dragObject("circle", "gradientBox",
circleLowBounds, circleUpBounds,
circleDown, circleMoved, endMovement);
colorChanged('box');
</script>
<body>
</html>
02/09/2008 - 06:34
Here's an enhanced version of this color picker:
http://walidator.info/?s=colorpicker_en
05/31/2008 - 17:16
I also had a bizarre problem with this. It turns out that the link to the javascript *must* be like
not like
Anyway, it's a great script. Thanks ferret.
05/31/2008 - 17:17
Um, that is, like
<script src=“javascript.js” type=“text/javascript”></script>
not
<script src=“javascript.js” type=“text/javascript”/>
06/01/2008 - 11:12
Kniffler, I've done that by accident way too many times. Also, you can refer to this post on how to embed code into any comments.
06/25/2008 - 07:26
Hi. I'd just ask for some advise on how I could modify this script to reduce the size of the color picker and still get the correct values? I've tried limiting the bounds during initialization and resized the image. However, it doesn't provide the correct values. Which part of the script should I modify? Thanks a lot!
06/25/2008 - 08:01
Ok, it has been a while since I looked at this code, but I'm pretty sure you will need to change some numbers in three different functions:
arrowsMoved,circleMoved, andcolorChanged.Essentially, you want to replace references to 256 with your new size, and references to 255 with your size minus 1.
Oh, and you'll want to change the bounds on the arrows and circle to your new numbers. So this code:
var arrowsUpBounds = new Position(0, 251);
var circleLowBounds = new Position(-5, -5);
var circleUpBounds = new Position(250, 250);
Should become this:
var arrowsUpBounds = new Position(0, NEWSIZE-5);
var circleLowBounds = new Position(-5, -5);
var circleUpBounds = new Position(NEWSIZE-6, NEWSIZE-6);
In retrospect, I should have pulled the size out as a constant.
07/12/2008 - 00:15
+1 и ниипет!
07/22/2008 - 23:29
I can not able to concatenate the code properly...so it give so many errors...can any one send me the complete code structure in 1/2 file(s) plz.....
Thank you
08/05/2008 - 11:34
Thank you so much for this tutorial. I will plug-in this to a project I am working on. It works will with asp.net and it does not conflict with AJAX for .net.
thx a million
-Ray
08/29/2008 - 11:29
It works on my nokia e70!!! -)
09/19/2008 - 04:20
This is a great script, thanks!
Is it ok to use the code found here on a commercial site also as long as I modify the design a little?
09/19/2008 - 07:38
Sure, go ahead, use it for whatever you would like. That's why it is out here :)
10/10/2008 - 00:51
Excellent! Thanks for a good site, we are going to use this colorpicker for users to control the design of their own templates! Again, many thanks!
10/26/2008 - 19:34
Thanks for this excellent tutorial and script!
I included the color picker into a Greasemonkey script that highlights movie links on IMDb.com:
http://userscripts.org/scripts/show/35145
10/28/2008 - 00:47
Спасибо, отличный скрипт!!!
Thank you, excelent script!! =)
12/09/2008 - 00:44
Hi
The code is very useful.
But the images are not displaying.
Can you please send me the full code with images.
Thanking you.
03/31/2009 - 06:56
awesome code! thanks for sharing
05/18/2009 - 19:56
Great script, and amazing tutorial(s)! Thank you so much!
08/06/2009 - 13:16
You are awesome!!!!! I had another color picker but it was way too many files to download and upload to the server for my taste and your code rocks!!!!!!
10/24/2009 - 13:02
Excellent script(s) !! I am new to JavaScript - had a question - how do I set the selected color in the opener page ? On the page I have a "color picker" graphic next to a textbox that opens up the color picker in a pop-up window. I have added a button just under the color picker (in the popup) that says "Set Color". I would like to add code to the "onclick" event of the button and be able to set the selected color in the text box.
Any help will be greatly appreciated.
10/24/2009 - 16:24
Nevermind, figured it out.
12/08/2009 - 10:54
Hi "The Tallest".
It's appropriate that your icon is Father Xmas because this script is an absolute gift.
Thanks and well done.
04/06/2010 - 21:12
I will plug-in this to a project I am working on. It works will with asp.net and it does not conflict with AJAX for .net.
club penguin cheats
04/22/2010 - 10:15
Thanks for this fantastic piece of code.
05/03/2010 - 16:11
Can you think of any reason this wouldn't work inside a 'lightbox' style jquery page? Possible variable name conflicts? anything like that?
I have a modular lightbox setup to run through a series of pages and render them in a lightbox type div. This code works fine outside jquery, but inside of it, the dragObject doesn't seem to get instantiated.
05/03/2010 - 21:54
Yea, just noticed the author hasn't been here in around 2 years.Good luck Feck!
05/18/2010 - 15:32
Thanks man i make this color picker on my site
05/22/2010 - 04:30
@amko_sa... (or any expert) can you make this for my site? which is powered by microsoft... it is more like a blog spot. Pls quote your fee. pls email to nahoku44@gmail.com thank you.
08/27/2010 - 10:19
haha thanks but i will go with YUI http://developer.yahoo.com/yui/examples/colorpicker/colorpicker-fromscript.html ;)
09/29/2010 - 05:55
Hey how do you tell which color the user has chosen? I mean how does it read from circle in the image? O_o
09/29/2010 - 08:46
Check out the functions arrowsMoved and circleMoved. The vertical slider represents the hue and the large gradient square represents the saturation. Since we know the size of these elements the values can be calculated based on the position of the mouse. If we know the hue and the saturation, a color can be derived.
01/17/2011 - 15:19
arrowsMoved and circleMoved have an extra, unused argument: element.
03/27/2011 - 12:08
ive tried adding this to HTML 5 and is doesn't work what can i do to fix this?
09/26/2011 - 22:38
thank you so much for this tutorial, it's really great script for me
11/09/2011 - 04:43
Hi,
Getting it up and running was easy. But I would need the hex codes without the # sign, or a coupled module won't work. I found this function:
{
var rStr = this.Red().toString(16);
if (rStr.length == 1)
rStr = '0' + rStr;
var gStr = this.Green().toString(16);
if (gStr.length == 1)
gStr = '0' + gStr;
var bStr = this.Blue().toString(16);
if (bStr.length == 1)
bStr = '0' + bStr;
return ('#' + rStr + gStr + bStr).toUpperCase();
}
but if I remove the '#', the color picker doesn't work anymore in most browsers, only in IE. Can this still be done?
11/09/2011 - 04:50
PS: to avoid mistakes: I only need the hex code to be without # sign in the form field. Whatever the color picker does internally is not important to me. In my setting, the hex code must be copied and pasted into a form field of external module. A module that I am neither able nor allowed to change.
12/26/2011 - 13:04
Thanks for this tutorial, work fine on my site!
http://www.imagemoz.com/rgb/
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.