From a7109fe0cb5b5af65ef77785c15207eb46482d98 Mon Sep 17 00:00:00 2001 From: tocque <364004564@qq.com> Date: Sat, 22 Dec 2018 23:19:21 +0900 Subject: [PATCH] colorPicker --- _server/colorPicker/colorPicker.data.js | 28 + _server/colorPicker/colorPicker.js | 1414 +++++++++++++++++++++++ _server/colorPicker/colors.js | 732 ++++++++++++ _server/colorPicker/jsColor.js | 258 +++++ _server/css/editor.css | 23 + editor.html | 37 + 6 files changed, 2492 insertions(+) create mode 100644 _server/colorPicker/colorPicker.data.js create mode 100644 _server/colorPicker/colorPicker.js create mode 100644 _server/colorPicker/colors.js create mode 100644 _server/colorPicker/jsColor.js diff --git a/_server/colorPicker/colorPicker.data.js b/_server/colorPicker/colorPicker.data.js new file mode 100644 index 00000000..e4169baf --- /dev/null +++ b/_server/colorPicker/colorPicker.data.js @@ -0,0 +1,28 @@ +;(function(window, undefined){ + "use strict" + + // see colorPicker.html for the following encrypted variables... will only be used in buildView() + var _html = ('^§app alpha-bg-w">^§slds">^§sldl-1">$^§sldl-2">$^§sldl-3">$^§curm">$^§sldr-1">$^§sldr-2">$^§sldr-4">$^§curl">$^§curr">$$^§opacity">|^§opacity-slider">$$$^§memo">^§raster">$^§raster-bg">$|$|$|$|$|$|$|$|$^§memo-store">$^§memo-cursor">$$^§panel">^§hsv">^hsl-mode §ß">$^hsv-h-ß §ß">H$^hsv-h-~ §~">-^§nsarrow">$$^hsl-h-@ §@">H$^hsv-s-ß §ß">S$^hsv-s-~ §~">-$^hsl-s-@ §@">S$^hsv-v-ß §ß">B$^hsv-v-~ §~">-$^hsl-l-@ §@">L$$^§hsl §hide">^hsv-mode §ß">$^hsl-h-ß §ß">H$^hsl-h-~ §~">-$^hsv-h-@ §@">H$^hsl-s-ß §ß">S$^hsl-s-~ §~">-$^hsv-s-@ §@">S$^hsl-l-ß §ß">L$^hsl-l-~ §~">-$^hsv-v-@ §@">B$$^§rgb">^rgb-r-ß §ß">R$^rgb-r-~ §~">-$^rgb-r-@ §ß"> $^rgb-g-ß §ß">G$^rgb-g-~ §~">-$^rgb-g-@ §ß"> $^rgb-b-ß §ß">B$^rgb-b-~ §~">-$^rgb-b-@ §ß"> $$^§cmyk">^Lab-mode §ß">$^cmyk-c-ß §@">C$^cmyk-c-~ §~">-$^Lab-L-@ §@">L$^cmyk-m-ß §@">M$^cmyk-m-~ §~">-$^Lab-a-@ §@">a$^cmyk-y-ß §@">Y$^cmyk-y-~ §~">-$^Lab-b-@ §@">b$^cmyk-k-ß §@">K$^cmyk-k-~ §~">-$^Lab-x-@ §ß"> $$^§Lab §hide">^cmyk-mode §ß">$^Lab-L-ß §@">L$^Lab-L-~ §~">-$^cmyk-c-@ §@">C$^Lab-a-ß §@">a$^Lab-a-~ §~">-$^cmyk-m-@ §@">M$^Lab-b-ß §@">b$^Lab-b-~ §~">-$^cmyk-y-@ §@">Y$^Lab-x-ß §@"> $^Lab-x-~ §~">-$^cmyk-k-@ §@">K$$^§alpha">^alpha-ß §ß">A$^alpha-~ §~">-$^alpha-@ §ß">W$$^§HEX">^HEX-ß §ß">#$^HEX-~ §~">-$^HEX-@ §ß">M$$^§ctrl">^§raster">$^§cont">$^§cold">$^§col1">| $$^§col2">| $$^§bres">RESET$^§bsav">SAVE$$$^§exit">$^§resize">$^§resizer">|$$$'). + replace(/\^/g, '
prevent showing the accelerator menu + // document.selection.empty(); + // } + window[cancelAnimationFrame](_renderTimer); + removeEvent(_isIE ? document.body : window, 'mousemove', _mouseMoveAction); + if (_delayState) { // hapens on inputs + _valueType = {type: 'alpha'}; + renderAll(); + } + // this is dirty... has to do with M|W|! button + if (typeof _mouseMoveAction === 'function' || typeof _mouseMoveAction === 'number') { + delete _options.webUnsave; + } + + _delayState = 1; + _mouseMoveAction = undefined; + + changeClass(_nodes.slds, 'do-drag', ''); + changeClass(_nodes.panel, '(?:start-change|do-change)', ''); + + _nodes.resizer.style.cssText = ''; + _nodes.panelCover.style.cssText = ''; + + _nodes.memo_store.style.cssText = 'background-color: ' + + color2string(_colors.RND.rgb) + '; ' + getOpacityCSS(_colors.alpha); + _nodes.memo.className = _nodes.memo.className.replace(/\s+(?:dark|light)/, '') + + // (/dark/.test(_nodes.colorPicker.className) ? ' dark' : ' light'); + (_colors['rgbaMix' + _bgTypes[_options.alphaBG]].luminance < 0.22 ? ' dark' : ' light'); + // (_colors.rgbaMixCustom.luminance < 0.22 ? ' dark' : ' light') + + _valueType = undefined; + + resetCursors(); + + if (_options.actionCallback) { + _options.actionCallback(e, _action || mouseMoveAction.name || action || 'external'); + } + } + } + + function changeXYValue(e) { + var event = e || window.event, + scale = _options.scale, + page = getPageXY(event), + x = (page.X - _targetOrigin.left) * (scale === 4 ? 2 : scale), + y = (page.Y - _targetOrigin.top) * scale, + mode = _options.mode; + + _colors[mode.type][mode.x] = limitValue(x / 255, 0, 1); + _colors[mode.type][mode.y] = 1 - limitValue(y / 255, 0, 1); + convertColors(); + return preventDefault(event); + } + + function changeZValue(e) { // make this part of changeXYValue + var event = e || window.event, + page = getPageXY(event), + z = (page.Y - _targetOrigin.top) * _options.scale, + mode = _options.mode; + + _colors[mode.type][mode.z] = 1 - limitValue(z / 255, 0, 1); + convertColors(); + return preventDefault(event); + } + + function changeOpacityValue(e) { + var event = e || window.event, + page = getPageXY(event); + + _newData = true; + _colors.alpha = limitValue(_math.round( + (page.X - _targetOrigin.left) / _targetOrigin.width * 100), 0, 100 + ) / 100; + convertColors('alpha'); + return preventDefault(event); + } + + function changeInputValue(e) { + var event = e || window.event, + page = getPageXY(event), + delta = _startCoords.pageY - page.Y, + delayOffset = _options.delayOffset, + type = _valueType.type, + isAlpha = type === 'alpha', + ranges; + + if (_delayState || _math.abs(delta) >= delayOffset) { + if (!_delayState) { + _delayState = (delta > 0 ? -delayOffset : delayOffset) + + (+_mainTarget.firstChild.data) * (isAlpha ? 100 : 1); + _startCoords.pageY += _delayState; + delta += _delayState; + _delayState = 1; + changeClass(_nodes.panel, 'start-change', 'do-change'); + _nodes.panelCover.style.cssText = 'position:absolute;left:0;top:0;right:0;bottom:0'; + // window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); + document.activeElement.blur(); + _renderTimer = window[requestAnimationFrame](renderAll); + } + + if (type === 'cmyk' && _options.cmyOnly) { + type = 'cmy'; + } + + if (isAlpha) { + _newData = true; + _colors.alpha = limitValue(delta / 100, 0, 1); + } else { + ranges = _valueRanges[type][_valueType.z]; + _colors[type][_valueType.z] = type === 'Lab' ? limitValue(delta, ranges[0], ranges[1]) : + limitValue(delta / ranges[1], 0, 1); + } + convertColors(isAlpha ? 'alpha' : type); + // event.returnValue is deprecated. Please use the standard event.preventDefault() instead. + // event.returnValue = false; // see: pauseEvent(event); + return preventDefault(event); + } + } + + function keyControl(e) { // this is quite big for what it does... + var event = e || window.event, + keyCode = event.which || event.keyCode, + key = String.fromCharCode(keyCode), + elm = document.activeElement, + + cln = elm.className.replace(_options.CSSPrefix, '').split('-'), + type = cln[0], + mode = cln[1], + + isAlpha = type === 'alpha', + isHex = type === 'HEX', + arrowKey = {k40: -1, k38: 1, k34: -10, k33: 10}['k' + keyCode] / (isAlpha ? 100 : 1), + validKeys = {'HEX': /[0-9a-fA-F]/, 'Lab': /[\-0-9]/, 'alpha': /[\.0-9]/}[type] || /[0-9]/, + valueRange = _valueRanges[type][type] || _valueRanges[type][mode], // let op! + + textNode = elm.firstChild, // chnge on TAB key + rangeData = caret(elm), + origValue = textNode.data, // do not change + value, + val = origValue === '0' && !isHex ? [] : origValue.split(''); // gefixt + + if (/^(?:27|13)$/.test(keyCode)) { // ENTER || ESC + preventDefault(event); + elm.blur(); + } else if (event.type === 'keydown') { // functional keys + if (arrowKey) { // arrow/page keys + value = limitValue(_math.round((+origValue + arrowKey) * 1e+6) / 1e+6, valueRange[0], valueRange[1]); + } else if (/^(?:8|46)$/.test(keyCode)) { // DELETE / BACKSPACE + if (!rangeData.range) { + rangeData.range++; + rangeData.start -= keyCode === 8 ? 1 : 0; + } + val.splice(rangeData.start, rangeData.range); + value = val.join('') || '0'; // never loose elm.firstChild + } + + if (value !== undefined) { // prevent keypress + preventDefault(event, true); + } + } else if (event.type === 'keypress') { + if (!/^(?:37|39|8|46|9)$/.test(keyCode)) { // left, right,DEL, BACK, TAB for FF + preventDefault(event, true); + } + if (validKeys.test(key)) { // regular input + val.splice(rangeData.start, rangeData.range, key); + value = val.join(''); + } + rangeData.start++; + } + + if (keyCode === 13 && isHex) { + if (textNode.data.length % 3 === 0 || textNode.data === '0') { // textNode.data.length && + return _colorPicker.setColor(textNode.data === '0' ? '000' : textNode.data, 'rgb', _colors.alpha, true); + } else { + preventDefault(event, true); + return elm.focus(); + } + } + + if (isHex && value !== undefined) { + value = /^0+/.test(value) ? value : parseInt(''+value, 16) || 0; + } + + if (value !== undefined && value !== '' && +value >= valueRange[0] && +value <= valueRange[1]) { + if (isHex) { + value = value.toString(16).toUpperCase() || '0'; + } + if (isAlpha) { + _colors[type] = +value; + } else if (!isHex) { + _colors[type][mode] = +value / (type === 'Lab' ? 1 : valueRange[1]); + } + convertColors(isAlpha ? 'alpha' : type); + + preRenderAll(_colors); + _mouseMoveAction = true; + stopChange(e, event.type); + + textNode.data = value; // if + caret(elm, _math.min(elm.firstChild.data.length, rangeData.start < 0 ? 0 : rangeData.start)); + } + } + + function buttonActions(e) { + var event = e || window.event, + target = event.target || event.srcElement, + targetClass = target.className, + parent = target.parentNode, + options = _options, + RGB = _colors.RND.rgb, + customBG, alphaBG, + mode = _options.mode, + newMode = '', + prefix = options.CSSPrefix, + isModeButton = /(?:hs|rgb)/.test(parent.className) && /^[HSBLRG]$/.test( + target.firstChild ? target.firstChild.data : '' + ), + isDblClick = /dblc/.test(event.type), + buttonAction = ''; // think this over again.... + + if (isDblClick && !isModeButton) { + return; + } else if (targetClass.indexOf('-labl ' + prefix + 'labl') !== -1) { // HSB -> HSL; CMYK -> Lab buttons + changeClass(_nodes[targetClass.split('-')[0]], prefix + 'hide', ''); + changeClass(_nodes[parent.className.split('-')[1]], prefix + 'hide'); + } else if (targetClass.indexOf(prefix + 'butt') !== -1) { // BUTTONS + if (isModeButton) { // set render modes + if (isDblClick && _options.scale === 2) { + newMode = /hs/.test(mode.type) ? 'rgb' : /hide/.test(_nodes.hsl.className) ? 'hsv' : 'hsl'; + newMode = newMode + '-' + newMode[mode.type.indexOf(mode.z)]; + } + _colorPicker.setMode(newMode ? newMode : targetClass.replace('-butt', '').split(' ')[0]); + buttonAction = 'modeChange'; + } else if (/^[rgb]/.test(targetClass)) { // no vertical slider rendering in RGB mode + newMode = targetClass.split('-')[1]; + changeClass(_nodes.colorPicker, 'no-rgb-' + newMode, + (options['noRGB' + newMode] = !options['noRGB' + newMode]) ? undefined : ''); + buttonAction = 'noRGB' + newMode; + // preRenderAll(); + } else if (target === _nodes.alpha_labl) { // alpha button right (background of raster) + customBG = options.customBG; + alphaBG = options.alphaBG; + changeClass(_nodes.colorPicker, 'alpha-bg-' + alphaBG, 'alpha-bg-' + + (alphaBG = options.alphaBG = e.data || (alphaBG === 'w' ? (customBG ? 'c' : 'b') : + alphaBG === 'c' ? 'b' : 'w'))); + target.firstChild.data = alphaBG.toUpperCase(); + _nodes.ctrl.style.backgroundColor = _nodes.memo.style.backgroundColor = + alphaBG !== 'c' ? '' : 'rgb(' + _math.round(customBG.r * 255) + ', ' + + _math.round(customBG.g * 255) + ', ' + + _math.round(customBG.b * 255) + ')'; + _nodes.raster.style.cssText = _nodes.raster_bg.previousSibling.style.cssText = + alphaBG !== 'c' ? '' : getOpacityCSS(customBG.luminance < 0.22 ? 0.5 : 0.4); + buttonAction = 'alphaBackground'; + } else if (target === _nodes.alpha_butt) { // alpha button left (disable alpha rendering) + changeClass(_nodes.colorPicker, 'mute-alpha', (options.muteAlpha = !options.muteAlpha) ? undefined : ''); + buttonAction = 'alphaState'; + } else if (target === _nodes.HEX_butt) { // make it on/off + changeClass(_nodes.colorPicker, 'no-HEX', (options.HEXState = !options.HEXState) ? undefined : ''); + buttonAction = 'HEXState'; + } else if (target === _nodes.HEX_labl) { // web save state change + var isWebSave = _colors.saveColor === 'web save'; + + if (_colors.saveColor !== 'web smart' && !isWebSave) { + options.webUnsave = copyColor(RGB); + _colorPicker.setColor(_colors.webSmart, 'rgb'); + } else if (!isWebSave) { + if (!options.webUnsave) { + options.webUnsave = copyColor(RGB); + } + _colorPicker.setColor(_colors.webSave, 'rgb'); + } else { + _colorPicker.setColor(options.webUnsave, 'rgb'); + } + buttonAction = 'webColorState'; + } else if (/Lab-x-labl/.test(targetClass)) { //target === _nodes.cmyk_type) { + // switch between CMYK and CMY + changeClass(_nodes.colorPicker, 'cmy-only', (options.cmyOnly = !options.cmyOnly) ? undefined : ''); + buttonAction = 'cmykState'; + } + } else if (target === _nodes.bsav) { // SAVE + saveAsBackground(); + buttonAction = 'saveAsBackground'; + } else if (target === _nodes.bres) { // RESET + var tmpColor = copyColor(RGB), + tmpAlpha = _colors.alpha; + + // a bit heavy but... doesn't matter here + // newCol, type, alpha, forceRender + _colorPicker.setColor(options.color); + saveAsBackground(); + _colorPicker.setColor(tmpColor, 'rgb', tmpAlpha); + buttonAction = 'resetColor'; + } else if (parent === _nodes.col1) { // COLOR left + // _colors.hsv.h = (_colors.hsv.h + 0.5) % 1; // not acurate + _colors.hsv.h -= (_colors.hsv.h > 0.5 ? 0.5 : -0.5); + convertColors('hsv'); + buttonAction = 'shiftColor'; + + } else if (parent === _nodes.col2) { // COLOR right + _colorPicker.setColor(target.style.backgroundColor, 'rgb', _colors.background.alpha); + buttonAction = 'setSavedColor'; + } else if (parent === _nodes.memo) { // MEMORIES // revisit... + var resetBlink = function() { + if (_nodes.memos.blinker) _nodes.memos.blinker.style.cssText = _nodes.memos.cssText; + }, + doBlink = function(elm) { + _nodes.memos.blinker = elm; + elm.style.cssText = 'background-color:' + (_colors.RGBLuminance > 0.22 ? '#333' : '#DDD'); + window.setTimeout(resetBlink, 200); + }; + + if (target === _nodes.memo_cursor) { // save color in memo + resetBlink(); + _nodes.memos.blinker = undefined; + _nodes.testNode.style.cssText = _nodes.memo_store.style.cssText; + _nodes.memos.cssText = _nodes.testNode.style.cssText; // ...how browser sees css + for (var n = _nodes.memos.length - 1; n--; ) { // check if color already exists + if (_nodes.memos.cssText === _nodes.memos[n].style.cssText) { + doBlink(_nodes.memos[n]); // sets _nodes.memos.blinker + break; + } + } + if (!_nodes.memos.blinker) { // right shift colors + for (var n = _nodes.memos.length - 1; n--; ) { + _nodes.memos[n + 1].style.cssText = _nodes.memos[n].style.cssText; + } + _nodes.memos[0].style.cssText = _nodes.memo_store.style.cssText; + } + buttonAction = 'toMemory'; + } else { // reset color from memo + resetBlink(); + _colorPicker.setColor(target.style.backgroundColor, 'rgb', target.style.opacity || 1); + _nodes.memos.cssText = target.style.cssText; + doBlink(target); + // this is dirty... has to do with M|W|! button + _mouseMoveAction = 1; + buttonAction = 'fromMemory'; + } + + } + // think this over again, does this need to be like this?? + if (buttonAction) { + preRenderAll(_colors); + _mouseMoveAction = _mouseMoveAction || true; // !!!! search for: // this is dirty... + stopChange(e, buttonAction); + } + } + + function resizeApp(e, size) { + var event = e || window.event, + page = event ? getPageXY(event) : {}, + isSize = size !== undefined, + x = isSize ? size : page.X - _targetOrigin.left + 8, + y = isSize ? size : page.Y - _targetOrigin.top + 8, + values = [' S XS XXS', ' S XS', ' S', ''], + sizes = _options.sizes, // from getUISizes(); + currentSize = isSize ? size : + y < sizes.XXS[1] + 25 ? 0 : + x < sizes.XS[0] + 25 ? 1 : + x < sizes.S[0] + 25 || y < sizes.S[1] + 25 ? 2 : 3, + value = values[currentSize], + isXXS = false, + mode, + tmp = ''; + + if (_cashedVars.resizer !== value) { + isXXS = /XX/.test(value); + mode = _options.mode; + + if (isXXS && (!/hs/.test(mode.type) || mode.z === 'h')) { + tmp = mode.type + '-' + mode.z; + _colorPicker.setMode(/hs/.test(mode.type) ? mode.type + '-s': 'hsv-s'); + _options.mode.original = tmp; + } else if (mode.original) { + // setMode(mode) creates a new object so mode.original gets deleted automatically + _colorPicker.setMode(mode.original); + } + + _nodes.colorPicker.className = _nodes.colorPicker.className.replace(/\s+(?:S|XS|XXS)/g, '') + value; + _options.scale = isXXS ? 4 : /S/.test(value) ? 2 : 1; + _options.currentSize = currentSize; + + _cashedVars.resizer = value; + + // fix this... from this point on inside if() ... convertColors(); + _newData = true; + renderAll(); + resetCursors(); + } + + _nodes.resizer.style.cssText = 'display: block;' + + 'width: ' + (x > 10 ? x : 10) + 'px;' + + 'height: ' + (y > 10 ? y : 10) + 'px;'; + } + + // ------------------------------------------------------ // + // --- Colors calculation and rendering related stuff --- // + // -------------------------------------------------------// + + function setMode(mode) { + var ModeMatrix = { + rgb_r : {x: 'b', y: 'g'}, + rgb_g : {x: 'b', y: 'r'}, + rgb_b : {x: 'r', y: 'g'}, + + hsv_h : {x: 's', y: 'v'}, + hsv_s : {x: 'h', y: 'v'}, + hsv_v : {x: 'h', y: 's'}, + + hsl_h : {x: 's', y: 'l'}, + hsl_s : {x: 'h', y: 'l'}, + hsl_l : {x: 'h', y: 's'} + }, + key = mode.replace('-', '_'), + regex = '\\b(?:rg|hs)\\w\\-\\w\\b'; // \\b\\w{3}\\-\\w\\b'; + + // changeClass(_nodes.colorPicker, '(?:.*?)$', mode); + // changeClass(_nodes.colorPicker, '\\b\\w{3}\\-\\w\\b', mode); + // changeClass(_nodes.slds, '\\b\\w{3}\\-\\w\\b', mode); + changeClass(_nodes.panel, regex, mode); + changeClass(_nodes.slds, regex, mode); + + mode = mode.split('-'); + return _options.mode = { + type: mode[0], + x: ModeMatrix[key].x, + y: ModeMatrix[key].y, + z: mode[1] + }; + } + + function initSliders() { // function name... + var regex = /\s+(?:hue-)*(?:dark|light)/g, + className = 'className'; // minification + + _nodes.curl[className] = _nodes.curl[className].replace(regex, ''); // ..... + _nodes.curr[className] = _nodes.curr[className].replace(regex, ''); // ..... + _nodes.slds[className] = _nodes.slds[className].replace(regex, ''); + // var sldrs = ['sldr_2', 'sldr_4', 'sldl_3']; + // for (var n = sldrs.length; n--; ) { + // _nodes[sldrs[n]][className] = _options.CSSPrefix + sldrs[n].replace('_', '-'); + // } + _nodes.sldr_2[className] = _options.CSSPrefix + 'sldr-2'; + _nodes.sldr_4[className] = _options.CSSPrefix + 'sldr-4'; + _nodes.sldl_3[className] = _options.CSSPrefix + 'sldl-3'; + + for (var style in _nodes.styles) { + if (!style.indexOf('sld')) _nodes.styles[style].cssText = ''; + } + _cashedVars = {}; + } + + function resetCursors() { + // _renderVars.isNoRGB = undefined; + _nodes.styles.curr.cssText = _nodes.styles.curl.cssText; // only coordinates + _nodes.curl.className = _options.CSSPrefix + 'curl' + ( + _renderVars.noRGBZ ? ' ' + _options.CSSPrefix + 'curl-' +_renderVars.noRGBZ: ''); + _nodes.curr.className = _options.CSSPrefix + 'curr ' + _options.CSSPrefix + 'curr-' + + (_options.mode.z === 'h' ? _renderVars.HUEContrast : _renderVars.noRGBZ ? + _renderVars.noRGBZ : _renderVars.RGBLuminance); + } + + function convertColors(type) { + preRenderAll(_colorInstance.setColor(undefined, type || _options.mode.type)); + _newData = true; + } + + function saveAsBackground(refresh) { + _colorInstance.saveAsBackground(); + _nodes.styles.col2.cssText = 'background-color: ' + color2string(_colors.background.RGB) + ';' + + getOpacityCSS(_colors.background.alpha); + + if (refresh) { + preRenderAll(_colors); + // renderAll(); + } + return (_colors); + } + + function preRenderAll(colors) { + var _Math = _math, + renderVars = _renderVars, + bgType = _bgTypes[_options.alphaBG]; + + renderVars.hueDelta = _Math.round(colors['rgbaMixBGMix' + bgType].hueDelta * 100); + // renderVars.RGBLuminanceDelta = _Math.round(colors.RGBLuminanceDelta * 100); + renderVars.luminanceDelta = _Math.round(colors['rgbaMixBGMix' + bgType].luminanceDelta * 100); + renderVars.RGBLuminance = colors.RGBLuminance > 0.22 ? 'light' : 'dark'; + renderVars.HUEContrast = colors.HUELuminance > 0.22 ? 'light' : 'dark'; + // renderVars.contrast = renderVars.RGBLuminanceDelta > renderVars.hueDelta ? 'contrast' : ''; + renderVars.contrast = renderVars.luminanceDelta > renderVars.hueDelta ? 'contrast' : ''; + renderVars.readabiltiy = + colors['rgbaMixBGMix' + bgType].WCAG2Ratio >= 7 ? 'green' : + colors['rgbaMixBGMix' + bgType].WCAG2Ratio >= 4.5 ? 'orange': ''; + renderVars.noRGBZ = _options['no' + _options.mode.type.toUpperCase() + _options.mode.z] ? + (_options.mode.z === 'g' && colors.rgb.g < 0.59 || _options.mode.z === 'b' || _options.mode.z === 'r' ? + 'dark' : 'light') : undefined; + } + + function renderAll() { // maybe render alpha seperately... + if (_mouseMoveAction) { + // _renderTimer = window[requestAnimationFrame](renderAll); + if (!_newData) return (_renderTimer = window[requestAnimationFrame](renderAll)); + _newData = false; + } + // console.time('renderAll'); + var options = _options, + mode = options.mode, + scale = options.scale, + prefix = options.CSSPrefix, + colors = _colors, + nodes = _nodes, + CSS = nodes.styles, + textNodes = nodes.textNodes, + valueRanges = _valueRanges, + valueType = _valueType, + renderVars = _renderVars, + cashedVars = _cashedVars, + + _Math = _math, + _getOpacityCSS = getOpacityCSS, + _color2string = color2string, + + a = 0, + b = 0, + x = colors[mode.type][mode.x], + X = _Math.round(x * 255 / (scale === 4 ? 2 : scale)), + y_ = colors[mode.type][mode.y], + y = 1 - y_, + Y = _Math.round(y * 255 / scale), + z = 1 - colors[mode.type][mode.z], + Z = _Math.round(z * 255 / scale), + coords = (1 === 1) ? [x, y_] : [0, 0], // (1 === 2) button label up + + isRGB = mode.type === 'rgb', + isHue = mode.z === 'h', + isHSL = mode.type === 'hsl', + isHSL_S = isHSL && mode.z === 's', + moveXY = _mouseMoveAction === changeXYValue, + moveZ = _mouseMoveAction === changeZValue, + display, tmp, value, slider; + + if (isRGB) { + if (coords[0] >= coords[1]) b = 1; else a = 1; + if (cashedVars.sliderSwap !== a) { + nodes.sldr_2.className = options.CSSPrefix + 'sldr-' + (3 - a); + cashedVars.sliderSwap = a; + } + } + if ((isRGB && !moveZ) || (isHue && !moveXY) || (!isHue && !moveZ)) { + CSS[isHue ? 'sldl_2' : 'sldr_2'][isRGB ? 'cssText' : 'backgroundColor'] = + isRGB ? _getOpacityCSS((coords[a] - coords[b]) / (1 - (coords[b]) || 0)) : _color2string(colors.hueRGB); + } + if (!isHue) { + if (!moveZ) CSS.sldr_4.cssText = _getOpacityCSS(isRGB ? coords[b] : isHSL_S ? _Math.abs(1 - y * 2) : y); + if (!moveXY) CSS.sldl_3.cssText = _getOpacityCSS(isHSL && mode.z === 'l' ? _Math.abs(1 - z * 2) : z); + if (isHSL) { // switch slider class name for black/white color half way through in HSL(S|L) mode(s) + slider = isHSL_S ? 'sldr_4' : 'sldl_3'; + tmp = isHSL_S ? 'r-' : 'l-'; + value = isHSL_S ? (y > 0.5 ? 4 : 3) : (z > 0.5 ? 3 : 4); + + if (cashedVars[slider] !== value) { + nodes[slider].className = options.CSSPrefix + 'sld' + tmp + value; + cashedVars[slider] = value; + } + } + } + + if (!moveZ) CSS.curm.cssText = 'left: ' + X + 'px; top: ' + Y + 'px;'; + if (!moveXY) CSS.curl.top = Z + 'px'; + if (valueType) CSS.curr.top = Z + 'px'; // && valueType.type !== mode.type + if ((valueType && valueType.type === 'alpha') || _mainTarget === nodes.opacity) { + CSS.opacity_slider.left = options.opacityPositionRelative ? (colors.alpha * ( + (_targetOrigin.width || nodes.opacity.offsetWidth) - + (_targetOrigin.childWidth || nodes.opacity_slider.offsetWidth))) + 'px' : + (colors.alpha * 100) + '%'; + } + + CSS.col1.cssText = 'background-color: ' + _color2string(colors.RND.rgb) + '; ' + + (options.muteAlpha ? '' : _getOpacityCSS(colors.alpha)); + CSS.opacity.backgroundColor = _color2string(colors.RND.rgb); + CSS.cold.width = renderVars.hueDelta + '%'; + CSS.cont.width = renderVars.luminanceDelta + '%'; + + for (display in textNodes) { + tmp = display.split('_'); + if (options.cmyOnly) { + tmp[0] = tmp[0].replace('k', ''); + } + value = tmp[1] ? colors.RND[tmp[0]][tmp[1]] : colors.RND[tmp[0]] || colors[tmp[0]]; + if (cashedVars[display] !== value) { + cashedVars[display] = value; + textNodes[display].data = value > 359.5 && display !== 'HEX' ? 0 : value; + + if (display !== 'HEX' && !options.noRangeBackground) { + value = colors[tmp[0]][tmp[1]] !== undefined ? colors[tmp[0]][tmp[1]] : colors[tmp[0]]; + if (tmp[0] === 'Lab') { + value = (value - valueRanges[tmp[0]][tmp[1]][0]) / + (valueRanges[tmp[0]][tmp[1]][1] - valueRanges[tmp[0]][tmp[1]][0]); + } + CSS[display].backgroundPosition = _Math.round((1 - value) * 100) + '% 0%'; + } + } + } + // Lab out of gammut + tmp = colors._rgb ? [ + colors._rgb.r !== colors.rgb.r, + colors._rgb.g !== colors.rgb.g, + colors._rgb.b !== colors.rgb.b + ] : []; + if (tmp.join('') !== cashedVars.outOfGammut) { + nodes.rgb_r_labl.firstChild.data = tmp[0] ? '!' : ' '; + nodes.rgb_g_labl.firstChild.data = tmp[1] ? '!' : ' '; + nodes.rgb_b_labl.firstChild.data = tmp[2] ? '!' : ' '; + cashedVars.outOfGammut = tmp.join(''); + } + if (renderVars.noRGBZ) { + if (cashedVars.noRGBZ !== renderVars.noRGBZ) { + nodes.curl.className = prefix + 'curl ' + prefix + 'curl-' + renderVars.noRGBZ; + + if (!moveZ) { + nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.noRGBZ; + } + cashedVars.noRGBZ = renderVars.noRGBZ; + } + } + if (cashedVars.HUEContrast !== renderVars.HUEContrast && mode.z === 'h') { + nodes.slds.className = nodes.slds.className.replace(/\s+hue-(?:dark|light)/, '') + + ' hue-' + renderVars.HUEContrast; + if (!moveZ) { + nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.HUEContrast; + } + cashedVars.HUEContrast = renderVars.HUEContrast; + } else if (cashedVars.RGBLuminance !== renderVars.RGBLuminance) { // test for no else + nodes.colorPicker.className = nodes.colorPicker.className.replace(/\s+(?:dark|light)/, '') + + ' ' + renderVars.RGBLuminance; + if (!moveZ && mode.z !== 'h' && !renderVars.noRGBZ) { + nodes.curr.className = prefix + 'curr ' + prefix + 'curr-' + renderVars.RGBLuminance; + } + cashedVars.RGBLuminance = renderVars.RGBLuminance; + } + + if (cashedVars.contrast !== renderVars.contrast || cashedVars.readabiltiy !== renderVars.readabiltiy) { + nodes.ctrl.className = nodes.ctrl.className.replace(' contrast', '').replace(/\s*(?:orange|green)/, '') + + (renderVars.contrast ? ' ' + renderVars.contrast : '') + + (renderVars.readabiltiy ? ' ' + renderVars.readabiltiy : ''); + cashedVars.contrast = renderVars.contrast; + cashedVars.readabiltiy = renderVars.readabiltiy; + } + + if (cashedVars.saveColor !== colors.saveColor) { + nodes.HEX_labl.firstChild.data = !colors.saveColor ? '!' : colors.saveColor === 'web save' ? 'W' : 'M'; + cashedVars.saveColor = colors.saveColor; + } + + if (options.renderCallback) { + options.renderCallback(colors, mode); // maybe more parameters + } + + if (_mouseMoveAction) { + _renderTimer = window[requestAnimationFrame](renderAll); + } + + // console.timeEnd('renderAll') + } + + + // ------------------------------------------------------ // + // ------------------ helper functions ------------------ // + // -------------------------------------------------------// + + function copyColor(color) { + var newColor = {}; + + for (var n in color) { + newColor[n] = color[n]; + } + return newColor; + } + + // function color2string(color, type) { + // var out = [], + // n = 0; + + // type = type || 'rgb'; + // while (type.charAt(n)) { // IE7 // V8 type[n] || + // out.push(color[type.charAt(n)]); + // n++; + // } + // return type + '(' + out.join(', ') + ')'; + // } + + function color2string(color, type) { // ~2 x faster on V8 + var out = '', + t = (type || 'rgb').split(''), + n = t.length; + + for ( ; n--; ) { + out = ', ' + color[t[n]] + out; + } + return (type || 'rgb') + '(' + out.substr(2) + ')'; + } + + + function limitValue(value, min, max) { + // return Math.max(min, Math.min(max, value)); // faster?? + return (value > max ? max : value < min ? min : value); + } + + function getOpacityCSS(value) { + if (value === undefined) value = 1; + + if (_doesOpacity) { + return 'opacity: ' + (_math.round(value * 10000000000) / 10000000000) + ';'; // value.toFixed(16) = 99% slower + // some speed test: + // return ['opacity: ', (Math.round(value * 1e+10) / 1e+10), ';'].join(''); + } else { + return 'filter: alpha(opacity=' + _math.round(value * 100) + ');'; + } + } + + function preventDefault(e, skip) { + e.preventDefault ? e.preventDefault() : e.returnValue = false; + if (!skip) window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); + return false; + } + + function changeClass(elm, cln, newCln) { + return !elm ? false : elm.className = (newCln !== undefined ? + elm.className.replace(new RegExp('\\s+?' + cln, 'g'), newCln ? ' ' + newCln : '') : + elm.className + ' ' + cln); + } + + function getOrigin(elm) { + var box = (elm.getBoundingClientRect) ? elm.getBoundingClientRect() : {top: 0, left: 0}, + doc = elm && elm.ownerDocument, + body = doc.body, + win = doc.defaultView || doc.parentWindow || window, + docElem = doc.documentElement || body.parentNode, + clientTop = docElem.clientTop || body.clientTop || 0, // border on html or body or both + clientLeft = docElem.clientLeft || body.clientLeft || 0; + + return { + left: box.left + (win.pageXOffset || docElem.scrollLeft) - clientLeft, + top: box.top + (win.pageYOffset || docElem.scrollTop) - clientTop + }; + } + + function getPageXY(e) { + var doc = window.document; + + return { + X: e.pageX || e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft, + Y: e.pageY || e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop + }; + } + + function addEvent(obj, type, func) { + addEvent.cache = addEvent.cache || { + _get: function(obj, type, func, checkOnly) { + var cache = addEvent.cache[type] || []; + + for (var n = cache.length; n--; ) { + if (obj === cache[n].obj && '' + func === '' + cache[n].func) { + func = cache[n].func; + if (!checkOnly) { + cache[n] = cache[n].obj = cache[n].func = null; + cache.splice(n, 1); + } + return func; + } + } + }, + _set: function(obj, type, func) { + var cache = addEvent.cache[type] = addEvent.cache[type] || []; + + if (addEvent.cache._get(obj, type, func, true)) { + return true; + } else { + cache.push({ + func: func, + obj: obj + }); + } + } + }; + + if (!func.name && addEvent.cache._set(obj, type, func) || typeof func !== 'function') { + return; + } + + if (obj.addEventListener) obj.addEventListener(type, func, false); + else obj.attachEvent('on' + type, func); + } + + function removeEvent(obj, type, func) { + if (typeof func !== 'function') return; + if (!func.name) { + func = addEvent.cache._get(obj, type, func) || func; + } + + if (obj.removeEventListener) obj.removeEventListener(type, func, false); + else obj.detachEvent('on' + type, func); + } + + function caret(target, pos) { // only for contenteditable + var out = {}; + + if (pos === undefined) { // get + if (window.getSelection) { // HTML5 + target.focus(); + var range1 = window.getSelection().getRangeAt(0), + range2 = range1.cloneRange(); + range2.selectNodeContents(target); + range2.setEnd(range1.endContainer, range1.endOffset); + out = { + end: range2.toString().length, + range: range1.toString().length + }; + } else { // IE < 9 + target.focus(); + var range1 = document.selection.createRange(), + range2 = document.body.createTextRange(); + range2.moveToElementText(target); + range2.setEndPoint('EndToEnd', range1); + out = { + end: range2.text.length, + range: range1.text.length + }; + } + out.start = out.end - out.range; + return out; + } + // set + if (pos == -1) pos = target['text']().length; + + if (window.getSelection) { // HTML5 + target.focus(); + window.getSelection().collapse(target.firstChild, pos); + } else { // IE < 9 + var range = document.body.createTextRange(); + range.moveToElementText(target); + range.moveStart('character', pos); + range.collapse(true); + range.select(); + } + return pos; + } + + // ------------- requestAnimationFrame shim ------------- // + // ---------- quite optimized for minification ---------- // + + for(var n = vendors.length; n-- && !window[requestAnimationFrame]; ) { + window[requestAnimationFrame] = window[vendors[n] + 'Request' + animationFrame]; + window[cancelAnimationFrame] = window[vendors[n] + 'Cancel' + animationFrame] || + window[vendors[n] + 'CancelRequest' + animationFrame]; + } + + window[requestAnimationFrame] = window[requestAnimationFrame] || function(callback) { + // this is good enough... and better than setTimeout + return window.setTimeout(callback, 1000 / _options.fps); + // return _renderTimer ? _renderTimer : window.setInterval(callback, 1000 / _options.fps); + }; + + window[cancelAnimationFrame] = window[cancelAnimationFrame] || function(id) { + // console.log('OFF-', id + '-' + _renderTimer) + window.clearTimeout(id); + return _renderTimer = null; + }; + +})(window); \ No newline at end of file diff --git a/_server/colorPicker/colors.js b/_server/colorPicker/colors.js new file mode 100644 index 00000000..e3d52f46 --- /dev/null +++ b/_server/colorPicker/colors.js @@ -0,0 +1,732 @@ +;(function(window, undefined){ + "use strict" + + var _valueRanges = { + rgb: {r: [0, 255], g: [0, 255], b: [0, 255]}, + hsv: {h: [0, 360], s: [0, 100], v: [0, 100]}, + hsl: {h: [0, 360], s: [0, 100], l: [0, 100]}, + cmy: {c: [0, 100], m: [0, 100], y: [0, 100]}, + cmyk: {c: [0, 100], m: [0, 100], y: [0, 100], k: [0, 100]}, + Lab: {L: [0, 100], a: [-128, 127], b: [-128, 127]}, + XYZ: {X: [0, 100], Y: [0, 100], Z: [0, 100]}, + alpha: {alpha: [0, 1]}, + HEX: {HEX: [0, 16777215]} // maybe we don't need this + }, + + _instance = {}, + _colors = {}, + + // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html for more + XYZMatrix = { // Observer = 2° (CIE 1931), Illuminant = D65 + X: [ 0.4124564, 0.3575761, 0.1804375], + Y: [ 0.2126729, 0.7151522, 0.0721750], + Z: [ 0.0193339, 0.1191920, 0.9503041], + R: [ 3.2404542, -1.5371385, -0.4985314], + G: [-0.9692660, 1.8760108, 0.0415560], + B: [ 0.0556434, -0.2040259, 1.0572252] + }, + grey = {r: 0.298954, g: 0.586434, b: 0.114612}, // CIE-XYZ 1931 + luminance = {r: 0.2126, g: 0.7152, b: 0.0722}, // W3C 2.0 + + _math = window.Math, + _parseint = window.parseInt, + + Colors = window.Colors = function(options) { + this.colors = {RND: {}}; + this.options = { + color: 'rgba(204, 82, 37, 0.8)', // init value(s)... + XYZMatrix: XYZMatrix, + // XYZReference: {}, + grey: grey, + luminance: luminance, + valueRanges: _valueRanges + // customBG: '#808080' + // convertCallback: undefined, + // allMixDetails: false + }; + initInstance(this, options || {}); + }, + initInstance = function(THIS, options) { + var matrix, + importColor, + _options = THIS.options, + customBG; + + focusInstance(THIS); + for (var option in options) { + if (options[option] !== undefined) _options[option] = options[option]; + } + matrix = _options.XYZMatrix; + if (!options.XYZReference) _options.XYZReference = { + X: matrix.X[0] + matrix.X[1] + matrix.X[2], + Y: matrix.Y[0] + matrix.Y[1] + matrix.Y[2], + Z: matrix.Z[0] + matrix.Z[1] + matrix.Z[2] + }; + customBG = _options.customBG; + _options.customBG = (typeof customBG === 'string') ? ColorConverter.txt2color(customBG).rgb : customBG; + _colors = setColor(THIS.colors, _options.color, undefined, true); // THIS.colors = _colors = + }, + focusInstance = function(THIS) { + if (_instance !== THIS) { + _instance = THIS; + _colors = THIS.colors; + } + }; + + Colors.prototype.setColor = function(newCol, type, alpha) { + focusInstance(this); + if (newCol) { + return setColor(this.colors, newCol, type, undefined, alpha); + } else { + if (alpha !== undefined) { + this.colors.alpha = limitValue(alpha, 0, 1); + } + return convertColors(type); + } + }; + + Colors.prototype.getColor = function(type) { + var result = this.colors, n = 0; + + if (type) { + type = type.split('.'); + while (result[type[n]]) { + result = result[type[n++]]; + } + if (type.length !== n) { + result = undefined; + } + } + return result; + }; + + Colors.prototype.setCustomBackground = function(col) { // wild gues,... check again... + focusInstance(this); // needed??? + this.options.customBG = (typeof col === 'string') ? ColorConverter.txt2color(col).rgb : col; + // return setColor(this.colors, this.options.customBG, 'rgb', true); // !!!!RGB + return setColor(this.colors, undefined, 'rgb'); // just recalculate existing + }; + + Colors.prototype.saveAsBackground = function() { // alpha + focusInstance(this); // needed??? + // return setColor(this.colors, this.colors.RND.rgb, 'rgb', true); + return setColor(this.colors, undefined, 'rgb', true); + }; + + Colors.prototype.convertColor = function(color, type) { + var convert = ColorConverter, + ranges = _valueRanges, + types = type.split('2'), + fromType = types[0], + toType = types[1], + test = /(?:RG|HS|CM|LA)/, + normalizeFrom = test.test(fromType), + normalizeTo = test.test(toType), + exceptions = {LAB: 'Lab'}, + normalize = function(color, type, reverse) { + var result = {}, + Lab = type === 'Lab' ? 1 : 0; + + for (var n in color) { // faster (but bigger) way: if/else outside 2 for loops + result[n] = reverse ? + _math.round(color[n] * (Lab || ranges[type][n][1])) : + color[n] / (Lab || ranges[type][n][1]); + } + + return result; + }; + + fromType = ranges[fromType] ? fromType : exceptions[fromType] || fromType.toLowerCase(); + toType = ranges[toType] ? toType : exceptions[toType] || toType.toLowerCase(); + + if (normalizeFrom && type !== 'RGB2HEX') { // from ABC to abc + color = normalize(color, fromType); + } + color = fromType === toType ? color : ( // same type; returns same/normalized version + convert[fromType + '2' + toType] ? convert[fromType + '2' + toType](color, true) : // existing converter + toType === 'HEX' ? convert.RGB2HEX(type === 'RGB2HEX' ? color : normalize(fromType === 'rgb' ? color : + convert[fromType + '2rgb'](color, true), 'rgb', true)) : + convert['rgb2' + toType](convert[fromType + '2rgb'](color, true), true) // not in ColorConverter + ); + if (normalizeTo) { // from abc to ABC + color = normalize(color, toType, true); + } + + return color; + }; + + Colors.prototype.toString = function(colorMode, forceAlpha) { + return ColorConverter.color2text((colorMode || 'rgb').toLowerCase(), this.colors, forceAlpha); + }; + + + // ------------------------------------------------------ // + // ---------- Color calculation related stuff ---------- // + // -------------------------------------------------------// + + function setColor(colors, color, type, save, alpha) { // color only full range + if (typeof color === 'string') { + var color = ColorConverter.txt2color(color); // new object + type = color.type; + _colors[type] = color[type]; + alpha = alpha !== undefined ? alpha : color.alpha; + } else if (color) { + for (var n in color) { + colors[type][n] = type === 'Lab' ? + limitValue(color[n], _valueRanges[type][n][0], _valueRanges[type][n][1]) : + limitValue(color[n] / _valueRanges[type][n][1], 0 , 1); + } + } + if (alpha !== undefined) { + colors.alpha = limitValue(+alpha, 0, 1); + } + return convertColors(type, save ? colors : undefined); + } + + function saveAsBackground(RGB, rgb, alpha) { + var grey = _instance.options.grey, + color = {}; + + color.RGB = {r: RGB.r, g: RGB.g, b: RGB.b}; + color.rgb = {r: rgb.r, g: rgb.g, b: rgb.b}; + color.alpha = alpha; + // color.RGBLuminance = getLuminance(RGB); + color.equivalentGrey = _math.round(grey.r * RGB.r + grey.g * RGB.g + grey.b * RGB.b); + + color.rgbaMixBlack = mixColors(rgb, {r: 0, g: 0, b: 0}, alpha, 1); + color.rgbaMixWhite = mixColors(rgb, {r: 1, g: 1, b: 1}, alpha, 1); + color.rgbaMixBlack.luminance = getLuminance(color.rgbaMixBlack, true); + color.rgbaMixWhite.luminance = getLuminance(color.rgbaMixWhite, true); + + if (_instance.options.customBG) { + color.rgbaMixCustom = mixColors(rgb, _instance.options.customBG, alpha, 1); + color.rgbaMixCustom.luminance = getLuminance(color.rgbaMixCustom, true); + _instance.options.customBG.luminance = getLuminance(_instance.options.customBG, true); + } + + return color; + } + + function convertColors(type, colorObj) { + // console.time('convertColors'); + var _Math = _math, + colors = colorObj || _colors, + convert = ColorConverter, + options = _instance.options, + ranges = _valueRanges, + RND = colors.RND, + // type = colorType, // || _mode.type, + modes, mode = '', from = '', // value = '', + exceptions = {hsl: 'hsv', cmyk: 'cmy', rgb: type}, + RGB = RND.rgb, SAVE, SMART; + + if (type !== 'alpha') { + for (var typ in ranges) { + if (!ranges[typ][typ]) { // no alpha|HEX + if (type !== typ && typ !== 'XYZ') { + from = exceptions[typ] || 'rgb'; + colors[typ] = convert[from + '2' + typ](colors[from]); + } + + if (!RND[typ]) RND[typ] = {}; + modes = colors[typ]; + for(mode in modes) { + RND[typ][mode] = _Math.round(modes[mode] * (typ === 'Lab' ? 1 : ranges[typ][mode][1])); + } + } + } + if (type !== 'Lab') { + delete colors._rgb; + } + + RGB = RND.rgb; + colors.HEX = convert.RGB2HEX(RGB); + colors.equivalentGrey = + options.grey.r * colors.rgb.r + + options.grey.g * colors.rgb.g + + options.grey.b * colors.rgb.b; + colors.webSave = SAVE = getClosestWebColor(RGB, 51); + // colors.webSave.HEX = convert.RGB2HEX(colors.webSave); + colors.webSmart = SMART = getClosestWebColor(RGB, 17); + // colors.webSmart.HEX = convert.RGB2HEX(colors.webSmart); + colors.saveColor = + RGB.r === SAVE.r && RGB.g === SAVE.g && RGB.b === SAVE.b ? 'web save' : + RGB.r === SMART.r && RGB.g === SMART.g && RGB.b === SMART.b ? 'web smart' : ''; + colors.hueRGB = convert.hue2RGB(colors.hsv.h); + + if (colorObj) { + colors.background = saveAsBackground(RGB, colors.rgb, colors.alpha); + } + } // else RGB = RND.rgb; + + var rgb = colors.rgb, // for better minification... + alpha = colors.alpha, + luminance = 'luminance', + background = colors.background, + rgbaMixBlack, rgbaMixWhite, rgbaMixCustom, + rgbaMixBG, rgbaMixBGMixBlack, rgbaMixBGMixWhite, rgbaMixBGMixCustom, + _mixColors = mixColors, + _getLuminance = getLuminance, + _getWCAG2Ratio = getWCAG2Ratio, + _getHueDelta = getHueDelta; + + rgbaMixBlack = _mixColors(rgb, {r: 0, g: 0, b: 0}, alpha, 1); + rgbaMixBlack[luminance] = _getLuminance(rgbaMixBlack, true); + colors.rgbaMixBlack = rgbaMixBlack; + + rgbaMixWhite = _mixColors(rgb, {r: 1, g: 1, b: 1}, alpha, 1); + rgbaMixWhite[luminance] = _getLuminance(rgbaMixWhite, true); + colors.rgbaMixWhite = rgbaMixWhite; + + if (options.allMixDetails) { + rgbaMixBlack.WCAG2Ratio = _getWCAG2Ratio(rgbaMixBlack[luminance], 0); + rgbaMixWhite.WCAG2Ratio = _getWCAG2Ratio(rgbaMixWhite[luminance], 1); + + if (options.customBG) { + rgbaMixCustom = _mixColors(rgb, options.customBG, alpha, 1); + rgbaMixCustom[luminance] = _getLuminance(rgbaMixCustom, true); + rgbaMixCustom.WCAG2Ratio = _getWCAG2Ratio(rgbaMixCustom[luminance], options.customBG[luminance]); + colors.rgbaMixCustom = rgbaMixCustom; + } + + rgbaMixBG = _mixColors(rgb, background.rgb, alpha, background.alpha); + rgbaMixBG[luminance] = _getLuminance(rgbaMixBG, true); // ?? do we need this? + colors.rgbaMixBG = rgbaMixBG; + + rgbaMixBGMixBlack = _mixColors(rgb, background.rgbaMixBlack, alpha, 1); + rgbaMixBGMixBlack[luminance] = _getLuminance(rgbaMixBGMixBlack, true); + rgbaMixBGMixBlack.WCAG2Ratio = _getWCAG2Ratio(rgbaMixBGMixBlack[luminance], + background.rgbaMixBlack[luminance]); + /* ------ */ + rgbaMixBGMixBlack.luminanceDelta = _Math.abs( + rgbaMixBGMixBlack[luminance] - background.rgbaMixBlack[luminance]); + rgbaMixBGMixBlack.hueDelta = _getHueDelta(background.rgbaMixBlack, rgbaMixBGMixBlack, true); + /* ------ */ + colors.rgbaMixBGMixBlack = rgbaMixBGMixBlack; + + rgbaMixBGMixWhite = _mixColors(rgb, background.rgbaMixWhite, alpha, 1); + rgbaMixBGMixWhite[luminance] = _getLuminance(rgbaMixBGMixWhite, true); + rgbaMixBGMixWhite.WCAG2Ratio = _getWCAG2Ratio(rgbaMixBGMixWhite[luminance], + background.rgbaMixWhite[luminance]); + /* ------ */ + rgbaMixBGMixWhite.luminanceDelta = _Math.abs( + rgbaMixBGMixWhite[luminance] - background.rgbaMixWhite[luminance]); + rgbaMixBGMixWhite.hueDelta = _getHueDelta(background.rgbaMixWhite, rgbaMixBGMixWhite, true); + /* ------ */ + colors.rgbaMixBGMixWhite = rgbaMixBGMixWhite; + } + + if (options.customBG) { + rgbaMixBGMixCustom = _mixColors(rgb, background.rgbaMixCustom, alpha, 1); + rgbaMixBGMixCustom[luminance] = _getLuminance(rgbaMixBGMixCustom, true); + rgbaMixBGMixCustom.WCAG2Ratio = _getWCAG2Ratio(rgbaMixBGMixCustom[luminance], + background.rgbaMixCustom[luminance]); + colors.rgbaMixBGMixCustom = rgbaMixBGMixCustom; + /* ------ */ + rgbaMixBGMixCustom.luminanceDelta = _Math.abs( + rgbaMixBGMixCustom[luminance] - background.rgbaMixCustom[luminance]); + rgbaMixBGMixCustom.hueDelta = _getHueDelta(background.rgbaMixCustom, rgbaMixBGMixCustom, true); + /* ------ */ + } + + colors.RGBLuminance = _getLuminance(RGB); + colors.HUELuminance = _getLuminance(colors.hueRGB); + + // renderVars.readyToRender = true; + if (options.convertCallback) { + options.convertCallback(colors, type); //, convert); //, _mode); + } + + // console.timeEnd('convertColors') + // if (colorObj) + return colors; + } + + + // ------------------------------------------------------ // + // ------------------ color conversion ------------------ // + // -------------------------------------------------------// + + var ColorConverter = { + txt2color: function(txt) { + var color = {}, + parts = txt.replace(/(?:#|\)|%)/g, '').split('('), + values = (parts[1] || '').split(/,\s*/), + type = parts[1] ? parts[0].substr(0, 3) : 'rgb', + m = ''; + + color.type = type; + color[type] = {}; + if (parts[1]) { + for (var n = 3; n--; ) { + m = type[n] || type.charAt(n); // IE7 + color[type][m] = +values[n] / _valueRanges[type][m][1]; + } + } else { + color.rgb = ColorConverter.HEX2rgb(parts[0]); + } + // color.color = color[type]; + color.alpha = values[3] ? +values[3] : 1; + + return color; + }, + + color2text: function(colorMode, colors, forceAlpha) { + var alpha = forceAlpha !== false && _math.round(colors.alpha * 100) / 100, + hasAlpha = typeof alpha === 'number' && + forceAlpha !== false && (forceAlpha || alpha !== 1), + RGB = colors.RND.rgb, + HSL = colors.RND.hsl, + shouldBeHex = colorMode === 'hex' && hasAlpha, + isHex = colorMode === 'hex' && !shouldBeHex, + isRgb = colorMode === 'rgb' || shouldBeHex, + innerText = isRgb ? RGB.r + ', ' + RGB.g + ', ' + RGB.b : + !isHex ? HSL.h + ', ' + HSL.s + '%, ' + HSL.l + '%' : + '#' + colors.HEX; + + return isHex ? innerText : (shouldBeHex ? 'rgb' : colorMode) + + (hasAlpha ? 'a' : '') + '(' + innerText + (hasAlpha ? ', ' + alpha : '') + ')'; + }, + + RGB2HEX: function(RGB) { + return ( + (RGB.r < 16 ? '0' : '') + RGB.r.toString(16) + + (RGB.g < 16 ? '0' : '') + RGB.g.toString(16) + + (RGB.b < 16 ? '0' : '') + RGB.b.toString(16) + ).toUpperCase(); + }, + + HEX2rgb: function(HEX) { + HEX = HEX.split(''); // IE7 + return { + r: +('0x' + HEX[0] + HEX[HEX[3] ? 1 : 0]) / 255, + g: +('0x' + HEX[HEX[3] ? 2 : 1] + (HEX[3] || HEX[1])) / 255, + b: +('0x' + (HEX[4] || HEX[2]) + (HEX[5] || HEX[2])) / 255 + }; + }, + + hue2RGB: function(hue) { + var _Math = _math, + h = hue * 6, + mod = ~~h % 6, // Math.floor(h) -> faster in most browsers + i = h === 6 ? 0 : (h - mod); + + return { + r: _Math.round([1, 1 - i, 0, 0, i, 1][mod] * 255), + g: _Math.round([i, 1, 1, 1 - i, 0, 0][mod] * 255), + b: _Math.round([0, 0, i, 1, 1, 1 - i][mod] * 255) + }; + }, + + // ------------------------ HSV ------------------------ // + + rgb2hsv: function(rgb) { // faster + var _Math = _math, + r = rgb.r, + g = rgb.g, + b = rgb.b, + k = 0, chroma, min, s; + + if (g < b) { + g = b + (b = g, 0); + k = -1; + } + min = b; + if (r < g) { + r = g + (g = r, 0); + k = -2 / 6 - k; + min = _Math.min(g, b); // g < b ? g : b; ??? + } + chroma = r - min; + s = r ? (chroma / r) : 0; + return { + h: s < 1e-15 ? ((_colors && _colors.hsl && _colors.hsl.h) || 0) : + chroma ? _Math.abs(k + (g - b) / (6 * chroma)) : 0, + s: r ? (chroma / r) : ((_colors && _colors.hsv && _colors.hsv.s) || 0), // ??_colors.hsv.s || 0 + v: r + }; + }, + + hsv2rgb: function(hsv) { + var h = hsv.h * 6, + s = hsv.s, + v = hsv.v, + i = ~~h, // Math.floor(h) -> faster in most browsers + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6; + + return { + r: [v, q, p, p, t, v][mod], + g: [t, v, v, q, p, p][mod], + b: [p, p, t, v, v, q][mod] + }; + }, + + // ------------------------ HSL ------------------------ // + + hsv2hsl: function(hsv) { + var l = (2 - hsv.s) * hsv.v, + s = hsv.s * hsv.v; + + s = !hsv.s ? 0 : l < 1 ? (l ? s / l : 0) : s / (2 - l); + + return { + h: hsv.h, + s: !hsv.v && !s ? ((_colors && _colors.hsl && _colors.hsl.s) || 0) : s, // ??? + l: l / 2 + }; + }, + + rgb2hsl: function(rgb, dependent) { // not used in Color + var hsv = ColorConverter.rgb2hsv(rgb); + + return ColorConverter.hsv2hsl(dependent ? hsv : (_colors.hsv = hsv)); + }, + + hsl2rgb: function(hsl) { + var h = hsl.h * 6, + s = hsl.s, + l = hsl.l, + v = l < 0.5 ? l * (1 + s) : (l + s) - (s * l), + m = l + l - v, + sv = v ? ((v - m) / v) : 0, + sextant = ~~h, // Math.floor(h) -> faster in most browsers + fract = h - sextant, + vsf = v * sv * fract, + t = m + vsf, + q = v - vsf, + mod = sextant % 6; + + return { + r: [v, q, m, m, t, v][mod], + g: [t, v, v, q, m, m][mod], + b: [m, m, t, v, v, q][mod] + }; + }, + + // ------------------------ CMYK ------------------------ // + // Quote from Wikipedia: + // "Since RGB and CMYK spaces are both device-dependent spaces, there is no + // simple or general conversion formula that converts between them. + // Conversions are generally done through color management systems, using + // color profiles that describe the spaces being converted. Nevertheless, the + // conversions cannot be exact, since these spaces have very different gamuts." + // Translation: the following are just simple RGB to CMY(K) and visa versa conversion functions. + + rgb2cmy: function(rgb) { + return { + c: 1 - rgb.r, + m: 1 - rgb.g, + y: 1 - rgb.b + }; + }, + + cmy2cmyk: function(cmy) { + var _Math = _math, + k = _Math.min(_Math.min(cmy.c, cmy.m), cmy.y), + t = 1 - k || 1e-20; + + return { // regular + c: (cmy.c - k) / t, + m: (cmy.m - k) / t, + y: (cmy.y - k) / t, + k: k + }; + }, + + cmyk2cmy: function(cmyk) { + var k = cmyk.k; + + return { // regular + c: cmyk.c * (1 - k) + k, + m: cmyk.m * (1 - k) + k, + y: cmyk.y * (1 - k) + k + }; + }, + + cmy2rgb: function(cmy) { + return { + r: 1 - cmy.c, + g: 1 - cmy.m, + b: 1 - cmy.y + }; + }, + + rgb2cmyk: function(rgb, dependent) { + var cmy = ColorConverter.rgb2cmy(rgb); // doppelt?? + + return ColorConverter.cmy2cmyk(dependent ? cmy : (_colors.cmy = cmy)); + }, + + cmyk2rgb: function(cmyk, dependent) { + var cmy = ColorConverter.cmyk2cmy(cmyk); // doppelt?? + + return ColorConverter.cmy2rgb(dependent ? cmy : (_colors.cmy = cmy)); + }, + + // ------------------------ LAB ------------------------ // + + XYZ2rgb: function(XYZ, skip) { + var _Math = _math, + M = _instance.options.XYZMatrix, + X = XYZ.X, + Y = XYZ.Y, + Z = XYZ.Z, + r = X * M.R[0] + Y * M.R[1] + Z * M.R[2], + g = X * M.G[0] + Y * M.G[1] + Z * M.G[2], + b = X * M.B[0] + Y * M.B[1] + Z * M.B[2], + N = 1 / 2.4; + + M = 0.0031308; + + r = (r > M ? 1.055 * _Math.pow(r, N) - 0.055 : 12.92 * r); + g = (g > M ? 1.055 * _Math.pow(g, N) - 0.055 : 12.92 * g); + b = (b > M ? 1.055 * _Math.pow(b, N) - 0.055 : 12.92 * b); + + if (!skip) { // out of gammut + _colors._rgb = {r: r, g: g, b: b}; + } + + return { + r: limitValue(r, 0, 1), + g: limitValue(g, 0, 1), + b: limitValue(b, 0, 1) + }; + }, + + rgb2XYZ: function(rgb) { + var _Math = _math, + M = _instance.options.XYZMatrix, + r = rgb.r, + g = rgb.g, + b = rgb.b, + N = 0.04045; + + r = (r > N ? _Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92); + g = (g > N ? _Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92); + b = (b > N ? _Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92); + + return { + X: r * M.X[0] + g * M.X[1] + b * M.X[2], + Y: r * M.Y[0] + g * M.Y[1] + b * M.Y[2], + Z: r * M.Z[0] + g * M.Z[1] + b * M.Z[2] + }; + }, + + XYZ2Lab: function(XYZ) { + var _Math = _math, + R = _instance.options.XYZReference, + X = XYZ.X / R.X, + Y = XYZ.Y / R.Y, + Z = XYZ.Z / R.Z, + N = 16 / 116, M = 1 / 3, K = 0.008856, L = 7.787037; + + X = X > K ? _Math.pow(X, M) : (L * X) + N; + Y = Y > K ? _Math.pow(Y, M) : (L * Y) + N; + Z = Z > K ? _Math.pow(Z, M) : (L * Z) + N; + + return { + L: (116 * Y) - 16, + a: 500 * (X - Y), + b: 200 * (Y - Z) + }; + }, + + Lab2XYZ: function(Lab) { + var _Math = _math, + R = _instance.options.XYZReference, + Y = (Lab.L + 16) / 116, + X = Lab.a / 500 + Y, + Z = Y - Lab.b / 200, + X3 = _Math.pow(X, 3), + Y3 = _Math.pow(Y, 3), + Z3 = _Math.pow(Z, 3), + N = 16 / 116, K = 0.008856, L = 7.787037; + + return { + X: (X3 > K ? X3 : (X - N) / L) * R.X, + Y: (Y3 > K ? Y3 : (Y - N) / L) * R.Y, + Z: (Z3 > K ? Z3 : (Z - N) / L) * R.Z + }; + }, + + rgb2Lab: function(rgb, dependent) { + var XYZ = ColorConverter.rgb2XYZ(rgb); + + return ColorConverter.XYZ2Lab(dependent ? XYZ : (_colors.XYZ = XYZ)); + }, + + Lab2rgb: function(Lab, dependent) { + var XYZ = ColorConverter.Lab2XYZ(Lab); + + return ColorConverter.XYZ2rgb(dependent ? XYZ : (_colors.XYZ = XYZ), dependent); + } + }; + + // ------------------------------------------------------ // + // ------------------ helper functions ------------------ // + // -------------------------------------------------------// + + function getClosestWebColor(RGB, val) { + var out = {}, + tmp = 0, + half = val / 2; + + for (var n in RGB) { + tmp = RGB[n] % val; // 51 = 'web save', 17 = 'web smart' + out[n] = RGB[n] + (tmp > half ? val - tmp : -tmp); + } + return out; + } + + function getHueDelta(rgb1, rgb2, nominal) { + var _Math = _math; + + return (_Math.max(rgb1.r - rgb2.r, rgb2.r - rgb1.r) + + _Math.max(rgb1.g - rgb2.g, rgb2.g - rgb1.g) + + _Math.max(rgb1.b - rgb2.b, rgb2.b - rgb1.b)) * (nominal ? 255 : 1) / 765; + } + + function getLuminance(rgb, normalized) { + var div = normalized ? 1 : 255, + RGB = [rgb.r / div, rgb.g / div, rgb.b / div], + luminance = _instance.options.luminance; + + for (var i = RGB.length; i--; ) { + RGB[i] = RGB[i] <= 0.03928 ? RGB[i] / 12.92 : _math.pow(((RGB[i] + 0.055) / 1.055), 2.4); + } + return ((luminance.r * RGB[0]) + (luminance.g * RGB[1]) + (luminance.b * RGB[2])); + } + + function mixColors(topColor, bottomColor, topAlpha, bottomAlpha) { + var newColor = {}, + alphaTop = (topAlpha !== undefined ? topAlpha : 1), + alphaBottom = (bottomAlpha !== undefined ? bottomAlpha : 1), + alpha = alphaTop + alphaBottom * (1 - alphaTop); // 1 - (1 - alphaTop) * (1 - alphaBottom); + + for(var n in topColor) { + newColor[n] = (topColor[n] * alphaTop + bottomColor[n] * alphaBottom * (1 - alphaTop)) / alpha; + } + newColor.a = alpha; + return newColor; + } + + function getWCAG2Ratio(lum1, lum2) { + var ratio = 1; + + if (lum1 >= lum2) { + ratio = (lum1 + 0.05) / (lum2 + 0.05); + } else { + ratio = (lum2 + 0.05) / (lum1 + 0.05); + } + return _math.round(ratio * 100) / 100; + } + + function limitValue(value, min, max) { + // return Math.max(min, Math.min(max, value)); // faster?? + return (value > max ? max : value < min ? min : value); + } +})(window); diff --git a/_server/colorPicker/jsColor.js b/_server/colorPicker/jsColor.js new file mode 100644 index 00000000..a5eaa50b --- /dev/null +++ b/_server/colorPicker/jsColor.js @@ -0,0 +1,258 @@ +(function (window) { + window.jsColorPicker = function(selectors, config) { + var renderCallback = function(colors, mode) { + var options = this, + input = options.input, + patch = options.patch, + RGB = colors.RND.rgb, + HSL = colors.RND.hsl, + AHEX = options.isIE8 ? (colors.alpha < 0.16 ? '0' : '') + + (Math.round(colors.alpha * 100)).toString(16).toUpperCase() + colors.HEX : '', + RGBInnerText = RGB.r + ', ' + RGB.g + ', ' + RGB.b, + RGBAText = RGBInnerText + ', ' + colors.alpha, + isAlpha = colors.alpha !== 1 && !options.isIE8, + colorMode = input.getAttribute('data-colorMode'); + + patch.style.cssText = + 'color:' + (colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd') + ';' + // Black...??? + 'background-color: rgba(' + RGBAText + ');' + + 'filter:' + (options.isIE8 ? 'progid:DXImageTransform.Microsoft.gradient(' + // IE<9 + 'startColorstr=#' + AHEX + ',' + 'endColorstr=#' + AHEX + ')' : ''); + + input.value = RGBAText; + + if (options.displayCallback) { + options.displayCallback(colors, mode, options); + } + }, + extractValue = function(elm) { + return "rgba("+elm.value+")" || "rgba("+elm.getAttribute('value')+")" || elm.style.backgroundColor || 'rgba(0, 0, 0, 1)'; + }, + actionCallback = function(event, action) { + var options = this, + colorPicker = colorPickers.current; + + if (action === 'toMemory') { + var memos = colorPicker.nodes.memos, + backgroundColor = '', + opacity = 0, + cookieTXT = []; + + for (var n = 0, m = memos.length; n < m; n++) { + backgroundColor = memos[n].style.backgroundColor; + opacity = memos[n].style.opacity; + opacity = Math.round((opacity === '' ? 1 : opacity) * 100) / 100; + cookieTXT.push(backgroundColor. + replace(/, /g, ','). + replace('rgb(', 'rgba('). + replace(')', ',' + opacity + ')') + ); + } + cookieTXT = '\'' + cookieTXT.join('\',\'') + '\''; + ColorPicker.docCookies('colorPickerMemos' + (options.noAlpha ? 'NoAlpha' : ''), cookieTXT); + } else if (action === 'resizeApp') { + ColorPicker.docCookies('colorPickerSize', colorPicker.color.options.currentSize); + } else if (action === 'modeChange') { + var mode = colorPicker.color.options.mode; + + ColorPicker.docCookies('colorPickerMode', mode.type + '-' + mode.z); + } + }, + createInstance = function(elm, config) { + var initConfig = { + klass: window.ColorPicker, + input: elm, + patch: elm, + isIE8: !!document.all && !document.addEventListener, // Opera??? + // *** animationSpeed: 200, + // *** draggable: true, + margin: {left: -1, top: 2}, + customBG: '#FFFFFF', + // displayCallback: displayCallback, + /* --- regular colorPicker options from this point --- */ + color: extractValue(elm), + initStyle: 'display: none', + mode: ColorPicker.docCookies('colorPickerMode') || 'hsv-h', + // memoryColors: (function(colors, config) { + // return config.noAlpha ? + // colors.replace(/\,\d*\.*\d*\)/g, ',1)') : colors; + // })($.docCookies('colorPickerMemos'), config || {}), + memoryColors: ColorPicker.docCookies('colorPickerMemos' + + ((config || {}).noAlpha ? 'NoAlpha' : '')), + size: ColorPicker.docCookies('colorPickerSize') || 1, + renderCallback: renderCallback, + actionCallback: actionCallback + }; + + for (var n in config) { + initConfig[n] = config[n]; + } + return new initConfig.klass(initConfig); + }, + doEventListeners = function(elm, multiple, off) { + var onOff = off ? 'removeEventListener' : 'addEventListener', + inputListener = function(e) { + var index = multiple ? Array.prototype.indexOf.call(elms, this) : 0, + colorPicker = colorPickers[index] || + (colorPickers[index] = createInstance(this, config)), + options = colorPicker.color.options; + + options.color = extractValue(elm); // brings color to default on reset + //检查颜色合法性 + if (options.color == options.color.match(/rgba\([0-9 ]+,[0-9 ]+,[0-9 ]+,[0-9. ]+\)/)[0]) { + var chec = options.color.match(/[0-9.]+/g); + if (chec.length != 4) + return; + for (var i = 0; i < 3; i++) { + if (chec[i] != chec[i].match(/\d+/)[0] || +chec[i] < 0 || +chec[i] > 255) + return; + } + if (chec[3] != chec[3].match(/\d+(\.\d+)?/)[0] || parseFloat(chec[3]) > 1 || parseFloat(chec[3] < 0)) + return; + if (!multiple) { + colorPicker.setColor(extractValue(elm), undefined, undefined, true); + colorPicker.saveAsBackground(); + } + colorPickers.current = colorPickers[index]; + } + } + focusListener = function(e) { + elm = document.getElementById("colorPicker"); + var input = elm, + position = window.ColorPicker.getOrigin(input), + index = multiple ? Array.prototype.indexOf.call(elms, elm) : 0, + colorPicker = colorPickers[index] || + (colorPickers[index] = createInstance(elm, config)), + options = colorPicker.color.options, + colorPickerUI = colorPicker.nodes.colorPicker, + appendTo = (options.appendTo || document.body), + isStatic = /static/.test(window.getComputedStyle(appendTo).position), + atrect = isStatic ? {left: 0, top: 0} : appendTo.getBoundingClientRect(), + waitTimer = 0; + + options.color = extractValue(elm); // brings color to default on reset + colorPickerUI.style.cssText = + 'position: absolute;' + (!colorPickers[index].cssIsReady ? 'display: none;' : '') + + 'left:' + (position.left + options.margin.left - atrect.left) + 'px;' + + 'top:' + (position.top + +input.offsetHeight + options.margin.top - atrect.top) + 'px;'; + + if (!multiple) { + options.input = elm; + options.patch = elm; // check again??? + colorPicker.setColor(extractValue(elm), undefined, undefined, true); + colorPicker.saveAsBackground(); + } + colorPickers.current = colorPickers[index]; + appendTo.appendChild(colorPickerUI); + waitTimer = setInterval(function() { // compensating late style on onload in colorPicker + if (colorPickers.current.cssIsReady) { + waitTimer = clearInterval(waitTimer); + colorPickerUI.style.display = 'block'; + } + }, 10); + }, + mousDownListener = function(e) { + var colorPicker = colorPickers.current, + colorPickerUI = (colorPicker ? colorPicker.nodes.colorPicker : undefined), + animationSpeed = colorPicker ? colorPicker.color.options.animationSpeed : 0, + isColorPicker = colorPicker && (function(elm) { + while (elm) { + if ((elm.className || '').indexOf('cpPanel') !== -1) return elm; + elm = elm.parentNode; + } + return false; + })(e.target), + inputIndex = Array.prototype.indexOf.call(elms, e.target); + + if (isColorPicker && Array.prototype.indexOf.call(colorPickers, isColorPicker)) { + if (e.target === colorPicker.nodes.exit) { + colorPickerUI.parentNode.style.display = 'none'; + document.activeElement.blur(); + } else { + // ... + } + } else if (inputIndex !== -1) { + // ... + } else if (colorPickerUI) { + colorPickerUI.parentNode.style.display = 'none'; + } + }; + button = document.getElementById("colorSwitch"); + button[onOff]('click', focusListener); + elm[onOff]('input', inputListener); + + if (!colorPickers.evt || off) { + colorPickers.evt = true; // prevent new eventListener for window + + window[onOff]('mousedown', mousDownListener); + } + }, + // this is a way to prevent data binding on HTMLElements + colorPickers = window.jsColorPicker.colorPickers || [], + elms = document.querySelectorAll(selectors), + testColors = new window.Colors({customBG: config.customBG, allMixDetails: true}); + + window.jsColorPicker.colorPickers = colorPickers; + + for (var n = 0, m = elms.length; n < m; n++) { + var elm = elms[n]; + + if (config === 'destroy') { + doEventListeners(elm, (config && config.multipleInstances), true); + if (colorPickers[n]) { + colorPickers[n].destroyAll(); + } + } else { + var color = extractValue(elm); + var value = color.split('('); + + testColors.setColor(color); + if (config && config.init) { + config.init(elm, testColors.colors); + } + elm.setAttribute('data-colorMode', value[1] ? value[0].substr(0, 3) : 'HEX'); + doEventListeners(elm, (config && config.multipleInstances), false); + if (config && config.readOnly) { + elm.readOnly = true; + } + } + }; + + return window.jsColorPicker.colorPickers; + }; + + window.ColorPicker.docCookies = function(key, val, options) { + var encode = encodeURIComponent, decode = decodeURIComponent, + cookies, n, tmp, cache = {}, + days; + + if (val === undefined) { // all about reading cookies + cookies = document.cookie.split(/;\s*/) || []; + for (n = cookies.length; n--; ) { + tmp = cookies[n].split('='); + if (tmp[0]) cache[decode(tmp.shift())] = decode(tmp.join('=')); // there might be '='s in the value... + } + + if (!key) return cache; // return Json for easy access to all cookies + else return cache[key]; // easy access to cookies from here + } else { // write/delete cookie + options = options || {}; + + if (val === '' || options.expires < 0) { // prepare deleteing the cookie + options.expires = -1; + // options.path = options.domain = options.secure = undefined; // to make shure the cookie gets deleted... + } + + if (options.expires !== undefined) { // prepare date if any + days = new Date(); + days.setDate(days.getDate() + options.expires); + } + + document.cookie = encode(key) + '=' + encode(val) + + (days ? '; expires=' + days.toUTCString() : '') + + (options.path ? '; path=' + options.path : '') + + (options.domain ? '; domain=' + options.domain : '') + + (options.secure ? '; secure' : ''); + } + }; +})(this); \ No newline at end of file diff --git a/_server/css/editor.css b/_server/css/editor.css index ebd4b009..17649905 100644 --- a/_server/css/editor.css +++ b/_server/css/editor.css @@ -18,6 +18,29 @@ body { margin: 0 auto; } +.cp-app { + z-index: 250; +} + +#colorPanel { + position: absolute; + left: 110px; + top: 36px; + width: 168px; + height: 205px; + z-index: 240; + padding: 4px 6px; + background-color: #F5F5F5; + box-sizing: border-box; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +#colorPicker { + margin: 2px 0; + border-radius: 3px; + width: 104px; +} + #left, #mid, #right { border-radius: 2px; box-sizing: border-box; diff --git a/editor.html b/editor.html index bd022f4f..b82418e1 100644 --- a/editor.html +++ b/editor.html @@ -181,6 +181,11 @@
+ +
@@ -494,6 +499,38 @@ if (location.protocol.indexOf("http")!=0) { + + + + + +