blob: f2373e13afe2dd4b76fd0812cb23f1429c838acb [file] [log] [blame]
/**
* Gogo Internet Services Color Picker Javascript Widget
* colorPicker for short.
*
* @author James Sleeman <james@gogo.co.nz>
* @date June, 2005
*
* The colorPicker class provides access to a color map for selecting
* colors which will be passed back to a callback (usually such a callback would
* write the RGB hex value returned into a field, but that's up to you).
*
* The color map presented is a standard rectangular pallate with 0->360 degrees of
* hue on the Y axis and 0->100% saturation on the X axis, the value (brightness) is
* selectable as a vertical column of grey values. Also present is a one row of
* white->grey->black for easy selection of these colors.
*
* A checkbox is presented, which when checked will force the palatte into "web safe"
* mode, only colours in the "web safe palatte" of 216 colors will be shown, the palatte
* is adjusted so that the normal blend of colours are "rounded" to the nearest web safe
* one. It should be noted that "web safe" colours really are a thing of the past,
* not only can pretty much every body display several million colours, but it's actually
* been found that of those 216 web safe colours only 20 to 30 are actually going to be
* displayed equally on the majority of monitors, and those are mostly yellows!
*
* =Usage Example=
* {{{
* <!-- Here is the field --> <!-- And we will use this button to open the picker"
* <input type="text" id="myField" /> <input type="button" value="..." id="myButton" />
* <script>
* // now when the window loads link everything up
* window.onload = function()
* {
*
* var myField = document.getElementById('myField'); // Get our field
* var myButton = document.getElementById('myButton'); // And the button
* var myPicker = new colorPicker // Make a picker
* (
* {
* // Cellsize is the width and height of each colour cell
* cellsize: '5px',
* // Callback is the function to execute when we are done,
* // this one puts the color value into the field
* callback: function(color){myField.value=color},
* // Granularity defines the maximum number of colors per row/column
* // more colors (high number) gives a smooth gradient of colors
* // but it will take (much) longer to display, while a small number
* // displays quickly, but doesn't show as many different colors.
* // Experiement with it, 18 seems like a good number.
* granularity: 18,
* // Websafe specifies whether or not to include the Web Safe checkbox
* websafe: false,
* // Savecolors specifies the number of recently-selected colors to remember
* savecolors: 20
* }
* );
*
* // And now hookup the button to open the picker,
* // the function to do that is myPicker.open()
* // it accepts two parameters, the "anchorage" and the element to anchor to,
* // and an optional third parameter, an initial color code to show in
* // the text box and sample.
* //
* // anchorage is made up of two of the keywords bottom,top,left and right
* // left: the left edge of the picker will align to the left edge of the element
* // or right: the right edgeof the picker aligns to the right edge of the element
* // top: the picker will appear above the element
* // or bottom: the picker will appear below the element
*
* myButton.onclick =
* function()
* { // anchorage , element to anchor to
* myPicker.open('bottom,right', myButton, initcolor)
* };
* }
* </script>
* }}}
*/
ColorPicker._pluginInfo =
{
name : "colorPicker",
version : "$LastChangedRevision: 1402 $".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'),
developer: "James Sleeman",
developer_url: "http://www.gogo.co.nz/",
c_owner : "Gogo Internet Services",
license : "htmlArea",
sponsor : "Gogo Internet Services",
sponsor_url : "http://www.gogo.co.nz/"
};
function ColorPicker()
{
// dummy function for Xinha plugin api, note the different names
}
try {
if (window.opener && window.opener.Xinha)
{ // this prevents that the Xinha.colorPicker object of the opening window is replaced by the one loaded in the popup
var openerColorPicker = window.opener.Xinha.colorPicker;
Xinha._addEvent(window,'unload', function() {Xinha.colorPicker = openerColorPicker;});
}
} catch(e) {}
//the actual function is below
Xinha.colorPicker = function (params)
{
// if the savedColors is empty, try to read the savedColors from cookie
if ( Xinha.colorPicker.savedColors.length === 0 )
{
Xinha.colorPicker.loadColors();
}
this.is_ie_6 = (Xinha.is_ie && Xinha.ie_version < 7);
var picker = this;
var enablepick = false;
var enablevalue = false;
var pickrow = 0;
var pickcol = 0;
this.callback = params.callback?params.callback:function(color){alert('You picked ' + color );};
this.websafe = params.websafe?params.websafe:false;
this.savecolors = params.savecolors? params.savecolors: 20;
this.cellsize = parseInt(params.cellsize?params.cellsize:'10px', 10);
this.side = params.granularity?params.granularity:18;
var valuecol = this.side + 1;
var valuerow = this.side - 1;
this.value = 1;
this.saved_cells = null;
this.table = document.createElement('table');
this.table.className = "dialog";
this.table.cellSpacing = this.table.cellPadding = 0;
this.table.onmouseup = function()
{
enablepick = false;
enablevalue = false;
};
this.tbody = document.createElement('tbody');
this.table.appendChild(this.tbody);
this.table.style.border = '1px solid WindowFrame';
this.table.style.zIndex = '1050';
// Add a title bar and close button
var tr = document.createElement('tr');
var td = document.createElement('td');
td.colSpan = this.side;
td.className= "title";
td.style.fontFamily = 'small-caption,caption,sans-serif';
td.style.fontSize = 'x-small';
td.unselectable = "on";
td.style.MozUserSelect = "none";
td.style.cursor = "default";
td.appendChild(document.createTextNode(Xinha._lc('Click a color...', 'ColorPicker')));
td.style.borderBottom = '1px solid WindowFrame';
tr.appendChild(td);
td = null;
var td = document.createElement('td');
td.className= "title";
td.colSpan = 2;
td.style.fontFamily = 'Tahoma,Verdana,sans-serif';
td.style.borderBottom = '1px solid WindowFrame';
td.style.paddingRight = '0';
tr.appendChild(td);
var but = document.createElement('div');
but.title = Xinha._lc("Close", 'ColorPicker');
but.className= 'buttonColor';
but.style.height = '11px';
but.style.width = '11px';
but.style.cursor = 'pointer';
but.onclick = function() { picker.close(); };
but.appendChild(document.createTextNode('\u00D7'));
but.align = 'center';
but.style.verticalAlign = 'top';
but.style.position = 'relative';
but.style.cssFloat = 'right';
but.style.styleFloat = 'right';
but.style.padding = '0';
but.style.margin = '2px';
but.style.backgroundColor = 'transparent';
but.style.fontSize= '11px';
if ( !Xinha.is_ie) but.style.lineHeight= '9px'; // line-height:9px is better for centering the x, but IE cuts it off at the bottom :(
but.style.letterSpacing= '0';
td.appendChild(but);
this.tbody.appendChild(tr);
but = tr = td = null;
this.constrain_cb = document.createElement('input');
this.constrain_cb.type = 'checkbox';
this.chosenColor = document.createElement('input');
this.chosenColor.type = 'text';
this.chosenColor.maxLength = 7;
this.chosenColor.style.width = '50px';
this.chosenColor.style.fontSize = '11px';
this.chosenColor.onchange = function()
{
if(/#[0-9a-f]{6,6}/i.test(this.value))
{
picker.backSample.style.backgroundColor = this.value;
picker.foreSample.style.color = this.value;
}
};
this.backSample = document.createElement('div');
this.backSample.appendChild(document.createTextNode('\u00A0'));
this.backSample.style.fontWeight = 'bold';
this.backSample.style.fontFamily = 'small-caption,caption,sans-serif';
this.backSample.fontSize = 'x-small';
this.foreSample = document.createElement('div');
this.foreSample.appendChild(document.createTextNode(Xinha._lc('Sample', 'ColorPicker')));
this.foreSample.style.fontWeight = 'bold';
this.foreSample.style.fontFamily = 'small-caption,caption,sans-serif';
this.foreSample.fontSize = 'x-small';
/** Convert a decimal number to a two byte hexadecimal representation.
* Zero-pads if necessary.
*
* @param integer dec Integer from 0 -> 255
* @returns string 2 character hexadecimal (zero padded)
*/
function toHex(dec)
{
var h = dec.toString(16);
if(h.length < 2) { h = '0' + h; }
return h;
}
/** Convert a color object {red:x, green:x, blue:x} to an RGB hex triplet
* @param object tuple {red:0->255, green:0->255, blue:0->255}
* @returns string hex triplet (#rrggbb)
*/
function tupleToColor(tuple)
{
return '#' + toHex(tuple.red) + toHex(tuple.green) + toHex(tuple.blue);
}
/** Determine the nearest power of a number to another number
* (eg nearest power of 4 to 5 => 4, of 4 to 7 => 8)
*
* @usedby rgbToWebsafe
* @param number num number to round to nearest power of <power>
* @param number power number to find the nearest power of
* @returns number Nearest power of <power> to num.
*/
function nearestPowerOf(num,power)
{
return Math.round(Math.round(num / power) * power);
}
/** Concatenate the hex representation of dec to itself and return as an integer.
* eg dec = 10 -> A -> AA -> 170
*
* @usedby rgbToWebsafe
* @param dec integer
* @returns integer
*/
function doubleHexDec(dec)
{
return parseInt(dec.toString(16) + dec.toString(16), 16);
}
/** Convert a given RGB color to the nearest "Web-Safe" color. A websafe color only has the values
* 00, 33, 66, 99, CC and FF for each of the red, green and blue components (thus 6 shades of each
* in combination to produce 6 * 6 * 6 = 216 colors).
*
* @param color object {red:0->255, green:0->255, blue:0->255}
* @returns object {red:51|102|153|204|255, green:51|102|153|204|255, blue:51|102|153|204|255}
*/
function rgbToWebsafe(color)
{
// For each take the high byte, divide by three, round and multiply by three before rounding again
color.red = doubleHexDec(nearestPowerOf(parseInt(toHex(color.red).charAt(0), 16), 3));
color.blue = doubleHexDec(nearestPowerOf(parseInt(toHex(color.blue).charAt(0), 16), 3));
color.green = doubleHexDec(nearestPowerOf(parseInt(toHex(color.green).charAt(0), 16), 3));
return color;
}
/** Convert a combination of hue, saturation and value into an RGB color.
* Hue is defined in degrees, saturation and value as a floats between 0 and 1 (0% -> 100%)
*
* @param h float angle of hue around color wheel 0->360
* @param s float saturation of color (no color (grey)) 0->1 (vibrant)
* @param v float value (brightness) of color (black) 0->1 (bright)
* @returns object {red:0->255, green:0->255, blue:0->255}
* @seealso http://en.wikipedia.org/wiki/HSV_color_space
*/
function hsvToRGB(h,s,v)
{
var colors;
if(s === 0)
{
// GREY
colors = {red:v,green:v,blue:v};
}
else
{
h /= 60;
var i = Math.floor(h);
var f = h - i;
var p = v * (1 - s);
var q = v * (1 - s * f);
var t = v * (1 - s * (1 - f) );
switch(i)
{
case 0: colors = {red:v, green:t, blue:p}; break;
case 1: colors = {red:q, green:v, blue:p}; break;
case 2: colors = {red:p, green:v, blue:t}; break;
case 3: colors = {red:p, green:q, blue:v}; break;
case 4: colors = {red:t, green:p, blue:v}; break;
default:colors = {red:v, green:p, blue:q}; break;
}
}
colors.red = Math.ceil(colors.red * 255);
colors.green = Math.ceil(colors.green * 255);
colors.blue = Math.ceil(colors.blue * 255);
return colors;
}
var self = this;
function closeOnBodyClick (ev)
{
ev = ev ? ev : window.event;
el = ev.target ? ev.target : ev.srcElement;
do
{
if (el == self.table) return;
}
while (el = el.parentNode);
self.close();
}
/** Open the color picker
*
* @param string anchorage pair of sides of element to anchor the picker to
* "top,left" "top,right" "bottom,left" or "bottom,right"
* @param HTML_ELEMENT element the element to anchor the picker to sides of
*
* @note The element is just referenced here for positioning (anchoring), it
* does not automatically get the color copied into it. See the usage instructions
* for the class.
*/
this.open = function(anchorage,element,initcolor)
{
this.table.style.display = '';
this.pick_color();
if(initcolor && /#[0-9a-f]{6,6}/i.test(initcolor))
{
this.chosenColor.value = initcolor;
this.backSample.style.backgroundColor = initcolor;
this.foreSample.style.color = initcolor;
}
Xinha._addEvent(document.body,'mousedown',closeOnBodyClick);
// Find position of the element
this.table.style.position = 'absolute';
var e = element;
var top = 0;
var left = 0;
// Check for overflow:scroll elements which do not have position:relative
while(e.parentNode)
{
e = e.parentNode;
if(typeof e.tagName != 'undefined' && !e.tagName.toLowerCase().match(/body|html/))
{
if( ( e.scrollTop || e.scrollLeft ) && !e.style.position.match(/fixed|absolute|relative/))
{
Xinha.debugMsg('Warning, the Xinha editor is included in a '+e.tagName+' which has scroll (overflow) but is not positioned relative, absolute, or fixed. The ColorPicker plugin may not display in the correct location.', 'warn');
}
}
}
e = element;
do
{
if (e.style.position == 'fixed')
{
this.table.style.position = 'fixed';
}
if(e.tagName.toLowerCase() == 'body')
{
// I don't think we need adjust for scroll at all on body
// In standards these would be 0 for the body (vs document.documentElement.scrollTop/Left)
// in quirks they are not, and it doesn't work in quirks with them.
top += e.offsetTop; // - e.scrollTop;
left += e.offsetLeft;// - e.scrollLeft;
}
else
{
// Caution, unless an element is positioned (position: fixed/relative/absolute)
// then it will not be considered because it is not an offsetParent
// so if you haev an overflow:scroll; div containing your Xinha, then you
// must set position:relative; (or other position) on it in order to get it
// to be considered.
top += e.offsetTop - e.scrollTop;
left += e.offsetLeft - e.scrollLeft;
}
e = e.offsetParent;
}
while(e);
var x, y;
if(/top/.test(anchorage) || (top + this.table.offsetHeight > document.body.offsetHeight))
{
if(top - this.table.offsetHeight > 0)
{
this.table.style.top = (top - this.table.offsetHeight) + 'px';
}
else
{
this.table.style.top = 0;
}
}
else
{
this.table.style.top = (top + element.offsetHeight) + 'px';
}
if(/left/.test(anchorage) || (left + this.table.offsetWidth > document.body.offsetWidth))
{
if(left - (this.table.offsetWidth - element.offsetWidth) > 0 )
{
this.table.style.left = (left - (this.table.offsetWidth - element.offsetWidth)) + 'px';
}
else
{
this.table.style.left = 0;
}
}
else
{
this.table.style.left = left + 'px';
}
// IE6 ONLY - prevent windowed elements (<SELECT>) to render above the colorpicker
if (this.is_ie_6)
{
this.iframe.style.top = this.table.style.top;
this.iframe.style.left = this.table.style.left;
}
};
function pickCell(cell)
{
picker.chosenColor.value = cell.colorCode;
picker.backSample.style.backgroundColor = cell.colorCode;
picker.foreSample.style.color = cell.colorCode;
if((cell.hue >= 195 && cell.saturation > 0.5) ||
(cell.hue === 0 && cell.saturation === 0 && cell.value < 0.5) ||
(cell.hue !== 0 && picker.value < 0.75))
{
cell.style.borderColor = '#fff';
}
else
{
cell.style.borderColor = '#000';
}
pickrow = cell.thisrow;
pickcol = cell.thiscol;
}
function pickValue(cell)
{
// cell.style.borderWidth = '1px';
// cell.style.borderStyle = 'solid';
if(picker.value < 0.5)
{
cell.style.borderColor = '#fff';
}
else
{
cell.style.borderColor = '#000';
}
valuerow = cell.thisrow;
valuecol = cell.thiscol;
picker.chosenColor.value = picker.saved_cells[pickrow][pickcol].colorCode;
picker.backSample.style.backgroundColor = picker.saved_cells[pickrow][pickcol].colorCode;
picker.foreSample.style.color = picker.saved_cells[pickrow][pickcol].colorCode;
}
function unpickCell(row,col)
{
picker.saved_cells[row][col].style.borderColor = picker.saved_cells[row][col].colorCode;
}
/** Draw the color picker. */
this.pick_color = function()
{
var rows, cols;
var picker = this;
var huestep = 359/(this.side);
var saturstep = 1/(this.side - 1);
var valustep = 1/(this.side - 1);
var constrain = this.constrain_cb.checked;
if(this.saved_cells === null)
{
this.saved_cells = [];
for(var row = 0; row < this.side; row++)
{
var tr = document.createElement('tr');
this.saved_cells[row] = [];
for(var col = 0; col < this.side; col++)
{
var td = document.createElement('td');
if(constrain)
{
td.colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(huestep*row, saturstep*col, this.value)));
}
else
{
td.colorCode = tupleToColor(hsvToRGB(huestep*row, saturstep*col, this.value));
}
this.saved_cells[row][col] = td;
td.style.height = this.cellsize + 'px';
td.style.width = this.cellsize -2 +'px';
td.style.borderWidth = '1px';
td.style.borderStyle = 'solid';
td.style.borderColor = td.colorCode;
td.style.backgroundColor = td.colorCode;
if(row == pickrow && col == pickcol)
{
td.style.borderColor = '#000';
this.chosenColor.value = td.colorCode;
this.backSample.style.backgroundColor = td.colorCode;
this.foreSample.style.color = td.colorCode;
}
td.hue = huestep * row;
td.saturation = saturstep*col;
td.thisrow = row;
td.thiscol = col;
td.onmousedown = function()
{
enablepick = true;
// unpickCell(pickrow,pickcol);
picker.saved_cells[pickrow][pickcol].style.borderColor = picker.saved_cells[pickrow][pickcol].colorCode;
pickCell(this);
};
td.onmouseover = function()
{
if(enablepick)
{
pickCell(this);
}
};
td.onmouseout = function()
{
if(enablepick)
{
// this.style.borderColor = picker.saved_cells[this.thisrow][this.thiscol].colorCode;
this.style.borderColor = this.colorCode;
}
};
td.ondblclick = function() { Xinha.colorPicker.remember(this.colorCode, picker.savecolors); picker.callback(this.colorCode); picker.close(); };
td.appendChild(document.createTextNode(' '));
td.style.cursor = 'pointer';
tr.appendChild(td);
td = null;
}
// Add a blank and then a value column
var td = document.createElement('td');
td.appendChild(document.createTextNode(' '));
td.style.width = this.cellsize + 'px';
tr.appendChild(td);
td = null;
var td = document.createElement('td');
this.saved_cells[row][col+1] = td;
td.appendChild(document.createTextNode(' '));
td.style.width = this.cellsize -2 + 'px';
td.style.height = this.cellsize + 'px';
td.constrainedColorCode = tupleToColor(rgbToWebsafe(hsvToRGB(0,0,valustep*row)));
td.style.backgroundColor = td.colorCode = tupleToColor(hsvToRGB(0,0,valustep*row));
td.style.borderWidth = '1px';
td.style.borderStyle = 'solid';
// td.style.borderColor = td.style.backgroundColor;
td.style.borderColor = td.colorCode;
if(row == valuerow)
{
td.style.borderColor = 'black';
}
td.hue = huestep * row;
td.saturation = saturstep*col;
td.hsv_value = valustep*row;
td.thisrow = row;
td.thiscol = col + 1;
td.onmousedown = function()
{
enablevalue = true;
// unpickCell(valuerow,valuecol);
picker.saved_cells[valuerow][valuecol].style.borderColor = picker.saved_cells[valuerow][valuecol].colorCode;
picker.value = this.hsv_value;
picker.pick_color();
pickValue(this);
};
td.onmouseover = function() {
if(enablevalue)
{
picker.value = this.hsv_value;
picker.pick_color();
pickValue(this);
}
};
td.onmouseout = function()
{
if(enablevalue)
{
// this.style.borderWidth = 0;
// this.style.borderStyle = 'none';
this.style.borderColor = this.colorCode;//'';
}
};
td.style.cursor = 'pointer';
tr.appendChild(td);
td = null;
this.tbody.appendChild(tr);
tr = null;
}
// Add one row of greys
var tr = document.createElement('tr');
this.saved_cells[row] = [];
for(var col = 0; col < this.side; col++)
{
var td = document.createElement('td');
if(constrain)
{
td.colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(0, 0, valustep*(this.side-col-1))));
}
else
{
td.colorCode = tupleToColor(hsvToRGB(0, 0, valustep*(this.side-col-1)));
}
this.saved_cells[row][col] = td;
td.style.height = this.cellsize + 'px';
td.style.width = this.cellsize -2 +'px';
td.style.borderWidth = '1px';
td.style.borderStyle = 'solid';
td.style.borderColor = td.colorCode;
td.style.backgroundColor = td.colorCode;
td.hue = 0;
td.saturation = 0;
td.value = valustep*(this.side-col-1);
td.thisrow = row;
td.thiscol = col;
td.onmousedown = function()
{
enablepick = true;
// unpickCell(pickrow,pickcol);
picker.saved_cells[pickrow][pickcol].style.borderColor = picker.saved_cells[pickrow][pickcol].colorCode;
pickCell(this);
};
td.onmouseover = function()
{
if(enablepick)
{
pickCell(this);
}
};
td.onmouseout = function()
{
if(enablepick)
{
// this.style.borderColor = picker.saved_cells[this.thisrow][this.thiscol].colorCode;
this.style.borderColor = this.colorCode;
}
};
td.ondblclick = function() { Xinha.colorPicker.remember(this.colorCode, picker.savecolors); picker.callback(this.colorCode); picker.close(); };
td.appendChild(document.createTextNode(' '));
td.style.cursor = 'pointer';
tr.appendChild(td);
td = null;
}
this.tbody.appendChild(tr);
tr = null;
var tr = document.createElement('tr');
var td = document.createElement('td');
tr.appendChild(td);
td.colSpan = this.side + 2;
td.style.padding = '3px';
if ( this.websafe )
{
var div = document.createElement('div');
var label = document.createElement('label');
label.appendChild(document.createTextNode(Xinha._lc('Web Safe: ', 'ColorPicker')));
this.constrain_cb.onclick = function() { picker.pick_color(); };
label.appendChild(this.constrain_cb);
label.style.fontFamily = 'small-caption,caption,sans-serif';
label.style.fontSize = 'x-small';
div.appendChild(label);
td.appendChild(div);
div = null;
}
var div = document.createElement('div');
var label = document.createElement('label');
label.style.fontFamily = 'small-caption,caption,sans-serif';
label.style.fontSize = 'x-small';
label.appendChild(document.createTextNode(Xinha._lc('Color: ', 'ColorPicker')));
label.appendChild(this.chosenColor);
div.appendChild(label);
var but = document.createElement('span');
but.className = "buttonColor ";
but.style.fontSize = '13px';
but.style.width = '24px';
but.style.marginLeft = '2px';
but.style.padding = '0px 4px';
but.style.cursor = 'pointer';
but.onclick = function() { Xinha.colorPicker.remember(picker.chosenColor.value, picker.savecolors); picker.callback(picker.chosenColor.value); picker.close(); };
but.appendChild(document.createTextNode(Xinha._lc('OK', 'ColorPicker')));
but.align = 'center';
div.appendChild(but);
td.appendChild(div);
var sampleTable = document.createElement('table');
sampleTable.style.width = '100%';
var sampleBody = document.createElement('tbody');
sampleTable.appendChild(sampleBody);
var sampleRow = document.createElement('tr');
sampleBody.appendChild(sampleRow);
var leftSampleCell = document.createElement('td');
sampleRow.appendChild(leftSampleCell);
leftSampleCell.appendChild(this.backSample);
leftSampleCell.style.width = '50%';
var rightSampleCell = document.createElement('td');
sampleRow.appendChild(rightSampleCell);
rightSampleCell.appendChild(this.foreSample);
rightSampleCell.style.width = '50%';
td.appendChild(sampleTable);
var savedColors = document.createElement('div');
savedColors.style.clear = 'both';
function createSavedColors(color)
{
var is_ie = Xinha.is_ie;
var div = document.createElement('div');
div.style.width = picker.cellsize + 'px';//13px';
div.style.height = picker.cellsize + 'px';//13px';
div.style.margin = '1px';
div.style.border = '1px solid black';
div.style.cursor = 'pointer';
div.style.backgroundColor = color;
div.style[ is_ie ? 'styleFloat' : 'cssFloat'] = 'left';
// div.onclick = function() { picker.callback(color); picker.close(); };
div.ondblclick = function() { picker.callback(color); picker.close(); };
// div.onmouseover = function()
div.onclick = function()
{
picker.chosenColor.value = color;
picker.backSample.style.backgroundColor = color;
picker.foreSample.style.color = color;
};
savedColors.appendChild(div);
}
for ( var savedCols = 0; savedCols < Xinha.colorPicker.savedColors.length; savedCols++ )
{
createSavedColors(Xinha.colorPicker.savedColors[savedCols]);
}
td.appendChild(savedColors);
this.tbody.appendChild(tr);
document.body.appendChild(this.table);
//put an iframe behind the table to mask select lists in ie
// IE6 ONLY - prevent windowed elements (<SELECT>) to render above the colorpicker
if (this.is_ie_6)
{
if ( !this.iframe )
{
this.iframe = document.createElement('iframe');
this.iframe.frameBorder = 0;
this.iframe.src = "javascript:;";
this.iframe.style.position = "absolute";
this.iframe.style.width = this.table.offsetWidth;
this.iframe.style.height = this.table.offsetHeight;
this.iframe.style.zIndex = '1049';
document.body.insertBefore(this.iframe, this.table);
}
this.iframe.style.display = '';
}
}
else
{
for(var row = 0; row < this.side; row++)
{
for(var col = 0; col < this.side; col++)
{
if(constrain)
{
this.saved_cells[row][col].colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(huestep*row, saturstep*col, this.value)));
}
else
{
this.saved_cells[row][col].colorCode = tupleToColor(hsvToRGB(huestep*row, saturstep*col, this.value));
}
this.saved_cells[row][col].style.backgroundColor = this.saved_cells[row][col].colorCode;
this.saved_cells[row][col].style.borderColor = this.saved_cells[row][col].colorCode;
}
}
var pickcell = this.saved_cells[pickrow][pickcol];
this.chosenColor.value = pickcell.colorCode;
this.backSample.style.backgroundColor = pickcell.colorCode;
this.foreSample.style.color = pickcell.colorCode;
if((pickcell.hue >= 195 && pickcell.saturation > 0.5) ||
(pickcell.hue === 0 && pickcell.saturation === 0 && pickcell.value < 0.5) ||
(pickcell.hue !== 0 && picker.value < 0.75))
{
pickcell.style.borderColor = '#fff';
}
else
{
pickcell.style.borderColor = '#000';
}
}
};
/** Close the color picker */
this.close = function()
{
Xinha._removeEvent(document.body,'mousedown',closeOnBodyClick);
this.table.style.display = 'none';
// IE6 ONLY - prevent windowed elements (<SELECT>) to render above the colorpicker
if (this.is_ie_6)
{
if ( this.iframe ) { this.iframe.style.display = 'none'; }
}
};
} // end Xinha.colorPicker
// array of the saved colors
Xinha.colorPicker.savedColors = [];
// add the color to the savedColors
Xinha.colorPicker.remember = function(color, savecolors)
{
// check if this color is known
for ( var i = Xinha.colorPicker.savedColors.length; i--; )
{
if ( Xinha.colorPicker.savedColors[i] == color )
{
return false;
}
}
// insert the new color
Xinha.colorPicker.savedColors.splice(0, 0, color);
// limit elements
Xinha.colorPicker.savedColors = Xinha.colorPicker.savedColors.slice(0, savecolors);
//[mokhet] probably some more parameters to send to the cookie definition
// like domain, secure and such, especially with https connection i presume
// save the cookie
var expdate = new Date();
expdate.setMonth(expdate.getMonth() + 1);
document.cookie = 'XinhaColorPicker=' + escape (Xinha.colorPicker.savedColors.join('-')) + ';expires=' + expdate.toGMTString();
return true;
};
// try to read the colors from the cookie
Xinha.colorPicker.loadColors = function()
{
var index = document.cookie.indexOf('XinhaColorPicker');
if ( index != -1 )
{
var begin = (document.cookie.indexOf('=', index) + 1);
var end = document.cookie.indexOf(';', index);
if ( end == -1 ) { end = document.cookie.length; }
Xinha.colorPicker.savedColors = unescape(document.cookie.substring(begin, end)).split('-');
}
};
/** Create a neat little box next to an input field
* * shows actual color
* * opens colorPicker on click
* * has a button to clear the color with a click
*
* @param input (DOM element)
* @param optional pickerConfig configuration object for Xinha.colorPicker()
*/
Xinha.colorPicker.InputBinding = function(input,pickerConfig)
{
var doc = input.ownerDocument;
var main = doc.createElement('span');
main.className = "buttonColor";
var chooser = this.chooser = doc.createElement('span');
chooser.className = "chooser";
if (input.value) chooser.style.backgroundColor = input.value;
chooser.onmouseover = function() {chooser.className = "chooser buttonColor-hilite";};
chooser.onmouseout = function() {chooser.className = "chooser";};
chooser.appendChild(doc.createTextNode('\u00a0'));
main.appendChild(chooser);
var clearColor = doc.createElement('span');
clearColor.className = "nocolor";
clearColor.onmouseover = function() {clearColor.className = "nocolor buttonColor-hilite"; clearColor.style.color='#f00'};
clearColor.onmouseout = function() {clearColor.className = "nocolor"; clearColor.style.color='#000'};
clearColor.onclick = function() {input.value ='';chooser.style.backgroundColor = ''};
clearColor.appendChild(doc.createTextNode('\u00d7'));
main.appendChild(clearColor);
input.parentNode.insertBefore(main,input.nextSibling);
Xinha._addEvent(input,'change',function() {chooser.style.backgroundColor = this.value;})
pickerConfig = (pickerConfig) ? Xinha.cloneObject(pickerConfig) : { cellsize:'5px' };
pickerConfig.callback = (pickerConfig.callback) ? pickerConfig.callback : function(color) {chooser.style.backgroundColor = color;input.value=color;if(typeof input.oncolorpicked == 'function') input.oncolorpicked();};
chooser.onclick = function()
{
var colPicker = new Xinha.colorPicker(pickerConfig);
colPicker.open("",chooser, input.value );
}
Xinha.freeLater(this,"chooser");
}
Xinha.colorPicker.InputBinding.prototype.setColor = function (color)
{
this.chooser.style.backgroundColor = color;
}