| |
| /** |
| * 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; |
| } |