diff --git a/src/editor/components/jgraduate/ColorValuePicker.js b/src/editor/components/jgraduate/ColorValuePicker.js index 85d17c4c..a658ee6a 100644 --- a/src/editor/components/jgraduate/ColorValuePicker.js +++ b/src/editor/components/jgraduate/ColorValuePicker.js @@ -35,7 +35,7 @@ export default class ColorValuePicker { */ constructor (picker, color, bindedHex, alphaPrecision) { const that = this; // private properties and methods - const inputs = picker.find('td.Text input'); + const inputs = picker.querySelectorAll('td.Text input'); // input box key down - use arrows to alter color /** * @@ -283,21 +283,57 @@ export default class ColorValuePicker { ahex = null; } let - red = inputs.eq(3), - green = inputs.eq(4), - blue = inputs.eq(5), - alpha = inputs.length > 7 ? inputs.eq(6) : null, - hue = inputs.eq(0), - saturation = inputs.eq(1), - value = inputs.eq(2), - hex = inputs.eq(inputs.length > 7 ? 7 : 6), - ahex = inputs.length > 7 ? inputs.eq(8) : null; + red = inputs[3], + green = inputs[4], + blue = inputs[5], + alpha = inputs.length > 7 ? inputs[6] : null, + hue = inputs[0], + saturation = inputs[1], + value = inputs[2], + hex = inputs[(inputs.length > 7) ? 7 : 6], + ahex = inputs.length > 7 ? inputs[8] : null; $.extend(true, that, { // public properties and methods destroy }); - red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur); - red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown); + red.addEventListener('keyup', keyUp); + green.addEventListener('keyup', keyUp); + blue.addEventListener('keyup', keyUp); + hue.addEventListener('keyup', keyUp); + saturation.addEventListener('keyup', keyUp); + value.addEventListener('keyup', keyUp); + hex.addEventListener('keyup', keyUp); + + red.addEventListener('blur', blur); + green.addEventListener('blur', blur); + blue.addEventListener('blur', blur); + hue.addEventListener('blur', blur); + saturation.addEventListener('blur', blur); + value.addEventListener('blur', blur); + hex.addEventListener('blur', blur); + + red.addEventListener('keydown', keyDown); + green.addEventListener('keydown', keyDown); + blue.addEventListener('keydown', keyDown); + hue.addEventListener('keydown', keyDown); + saturation.addEventListener('keydown', keyDown); + value.addEventListener('keydown', keyDown); + + if (alpha !== null) { + alpha.addEventListener('keyup', keyUp); + alpha.addEventListener('blur', blur); + alpha.addEventListener('keydown', keyDown); + } + if (ahex !== null) { + ahex.addEventListener('keyup', keyUp); + ahex.addEventListener('blur', blur); + } + if (bindedHex !== null) { + bindedHex.addEventListener('keyup', keyUp); + bindedHex.addEventListener('blur', blur); + } + // red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur); + // red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown); color.bind(colorChanged); } } diff --git a/src/editor/components/jgraduate/Slider.js b/src/editor/components/jgraduate/Slider.js new file mode 100644 index 00000000..315e30d5 --- /dev/null +++ b/src/editor/components/jgraduate/Slider.js @@ -0,0 +1,360 @@ +/* globals $ */ +/* eslint-disable unicorn/prefer-math-trunc */ +/* eslint-disable no-bitwise */ +/* eslint-disable unicorn/prefer-ternary */ +/** + * Whether a value is `null` or `undefined`. + * @param {any} val + * @returns {boolean} + */ +const isNullish = (val) => { + return val === null || val === undefined; +}; +/** + * Encapsulate slider functionality for the ColorMap and ColorBar - + * could be useful to use a jQuery UI draggable for this with certain extensions. + * @memberof module:jPicker + */ +export default class Slider { + /** + * @param {external:jQuery} bar + * @param {module:jPicker.SliderOptions} options + */ + constructor (bar, options) { + const that = this; + /** + * Fire events on the supplied `context` + * @param {module:jPicker.JPickerInit} context + * @returns {void} + */ + function fireChangeEvents (context) { + changeEvents.forEach((changeEvent) => { + changeEvent.call(that, that, context); + }); + } + + /** + * Bind the mousedown to the bar not the arrow for quick snapping to the clicked location. + * @param {external:jQuery.Event} e + * @returns {void} + */ + function mouseDown (e) { + const off = bar.offset(); + offset = {l: off.left | 0, t: off.top | 0}; + clearTimeout(timeout); + // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + timeout = setTimeout(function () { + setValuesFromMousePosition.call(that, e); + }, 0); + // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + document.addEventListener('mousemove', mouseMove); + document.addEventListener('mouseup', mouseUp); + // $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp); + e.preventDefault(); // don't try to select anything or drag the image to the desktop + } + /** + * Set the values as the mouse moves. + * @param {external:jQuery.Event} e + * @returns {false} + */ + function mouseMove (e) { + clearTimeout(timeout); + timeout = setTimeout(function () { + setValuesFromMousePosition.call(that, e); + }, 0); + e.stopPropagation(); + e.preventDefault(); + return false; + } + /** + * Unbind the document events - they aren't needed when not dragging. + * @param {external:jQuery.Event} e + * @returns {false} + */ + function mouseUp (e) { + document.removeEventListener('mousemove', mouseMove); + document.removeEventListener('mouseup', mouseUp); + // $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); + e.stopPropagation(); + e.preventDefault(); + return false; + } + + /** + * Calculate mouse position and set value within the current range. + * @param {Event} e + * @returns {void} + */ + function setValuesFromMousePosition (e) { + const barW = bar.w, // local copies for YUI compressor + barH = bar.h; + let locX = e.pageX - offset.l, + locY = e.pageY - offset.t; + // keep the arrow within the bounds of the bar + if (locX < 0) locX = 0; + else if (locX > barW) locX = barW; + if (locY < 0) locY = 0; + else if (locY > barH) locY = barH; + val.call(that, 'xy', { + x: ((locX / barW) * rangeX) + minX, + y: ((locY / barH) * rangeY) + minY + }); + } + /** + * + * @returns {void} + */ + function draw () { + const + barW = bar.w, + barH = bar.h, + arrowW = arrow.w, + arrowH = arrow.h; + let arrowOffsetX = 0, + arrowOffsetY = 0; + setTimeout(function () { + if (rangeX > 0) { // range is greater than zero + // constrain to bounds + if (x === maxX) arrowOffsetX = barW; + else arrowOffsetX = ((x / rangeX) * barW) | 0; + } + if (rangeY > 0) { // range is greater than zero + // constrain to bounds + if (y === maxY) arrowOffsetY = barH; + else arrowOffsetY = ((y / rangeY) * barH) | 0; + } + // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest) + else arrowOffsetX -= arrowW >> 1; + // if arrow height is greater than bar height, center arrow and prevent vertical dragging + if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1); + else arrowOffsetY -= arrowH >> 1; + // set the arrow position based on these offsets + arrow.css({left: arrowOffsetX + 'px', top: arrowOffsetY + 'px'}); + // arrow.style.left = arrowOffsetX + 'px'; + // arrow.style.top = arrowOffsetY + 'px'; + }); + } + + /** + * Get or set a value. + * @param {?("xy"|"x"|"y")} name + * @param {module:math.XYObject} value + * @param {module:jPicker.Slider} context + * @returns {module:math.XYObject|Float|void} + */ + function val (name, value, context) { + const set = value !== undefined; + if (!set) { + if (isNullish(name)) name = 'xy'; + switch (name.toLowerCase()) { + case 'x': return x; + case 'y': return y; + case 'xy': + default: return {x, y}; + } + } + if (!isNullish(context) && context === that) return undefined; + let changed = false; + + let newX, newY; + if (isNullish(name)) name = 'xy'; + switch (name.toLowerCase()) { + case 'x': + newX = (value && ((value.x && value.x | 0) || value | 0)) || 0; + break; + case 'y': + newY = (value && ((value.y && value.y | 0) || value | 0)) || 0; + break; + case 'xy': + default: + newX = (value && value.x && value.x | 0) || 0; + newY = (value && value.y && value.y | 0) || 0; + break; + } + if (!isNullish(newX)) { + if (newX < minX) newX = minX; + else if (newX > maxX) newX = maxX; + if (x !== newX) { + x = newX; + changed = true; + } + } + if (!isNullish(newY)) { + if (newY < minY) newY = minY; + else if (newY > maxY) newY = maxY; + if (y !== newY) { + y = newY; + changed = true; + } + } + changed && fireChangeEvents.call(that, context || that); + return undefined; + } + + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeX + * @property {Float} minX + * @property {Float} maxX + * @property {Float} rangeX + */ + /** + * @typedef {PlainObject} module:jPicker.MinMaxRangeY + * @property {Float} minY + * @property {Float} maxY + * @property {Float} rangeY + */ + /** + * @typedef {module:jPicker.MinMaxRangeY|module:jPicker.MinMaxRangeX} module:jPicker.MinMaxRangeXY + */ + + /** + * + * @param {"minx"|"maxx"|"rangex"|"miny"|"maxy"|"rangey"|"all"} name + * @param {module:jPicker.MinMaxRangeXY} value + * @returns {module:jPicker.MinMaxRangeXY|module:jPicker.MinMaxRangeX|module:jPicker.MinMaxRangeY|void} + */ + function range (name, value) { + const set = value !== undefined; + if (!set) { + if (isNullish(name)) name = 'all'; + switch (name.toLowerCase()) { + case 'minx': return minX; + case 'maxx': return maxX; + case 'rangex': return {minX, maxX, rangeX}; + case 'miny': return minY; + case 'maxy': return maxY; + case 'rangey': return {minY, maxY, rangeY}; + case 'all': + default: return {minX, maxX, rangeX, minY, maxY, rangeY}; + } + } + let // changed = false, + newMinX, + newMaxX, + newMinY, + newMaxY; + if (isNullish(name)) name = 'all'; + switch (name.toLowerCase()) { + case 'minx': + newMinX = (value && ((value.minX && value.minX | 0) || value | 0)) || 0; + break; + case 'maxx': + newMaxX = (value && ((value.maxX && value.maxX | 0) || value | 0)) || 0; + break; + case 'rangex': + newMinX = (value && value.minX && value.minX | 0) || 0; + newMaxX = (value && value.maxX && value.maxX | 0) || 0; + break; + case 'miny': + newMinY = (value && ((value.minY && value.minY | 0) || value | 0)) || 0; + break; + case 'maxy': + newMaxY = (value && ((value.maxY && value.maxY | 0) || value | 0)) || 0; + break; + case 'rangey': + newMinY = (value && value.minY && value.minY | 0) || 0; + newMaxY = (value && value.maxY && value.maxY | 0) || 0; + break; + case 'all': + default: + newMinX = (value && value.minX && value.minX | 0) || 0; + newMaxX = (value && value.maxX && value.maxX | 0) || 0; + newMinY = (value && value.minY && value.minY | 0) || 0; + newMaxY = (value && value.maxY && value.maxY | 0) || 0; + break; + } + + if (!isNullish(newMinX) && minX !== newMinX) { + minX = newMinX; + rangeX = maxX - minX; + } + if (!isNullish(newMaxX) && maxX !== newMaxX) { + maxX = newMaxX; + rangeX = maxX - minX; + } + if (!isNullish(newMinY) && minY !== newMinY) { + minY = newMinY; + rangeY = maxY - minY; + } + if (!isNullish(newMaxY) && maxY !== newMaxY) { + maxY = newMaxY; + rangeY = maxY - minY; + } + return undefined; + } + /** + * @param {GenericCallback} callback + * @returns {void} + */ + function bind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks + if (typeof callback === 'function') changeEvents.push(callback); + } + /** + * @param {GenericCallback} callback + * @returns {void} + */ + function unbind (callback) { // eslint-disable-line promise/prefer-await-to-callbacks + if (typeof callback !== 'function') return; + let i; + while ((i = changeEvents.includes(callback))) changeEvents.splice(i, 1); + } + /** + * + * @returns {void} + */ + function destroy () { + // unbind all possible events and null objects + document.removeEventListener('mousemove', mouseMove); + document.removeEventListener('mouseup', mouseUp); + bar.removeEventListener('mousedown', mouseDown); + // $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); + // bar.unbind('mousedown', mouseDown); + bar = null; + arrow = null; + changeEvents = null; + } + let offset, + timeout, + x = 0, + y = 0, + minX = 0, + maxX = 100, + rangeX = 100, + minY = 0, + maxY = 100, + rangeY = 100, + arrow = bar.querySelector('img'), // the arrow image to drag + changeEvents = []; + Object.assign(that, { + val, + range, + bind, + unbind, + destroy + }); + /* $.extend( + true, + // public properties, methods, and event bindings - these we need + // to access from other controls + that, + { + val, + range, + bind, + unbind, + destroy + } + ); */ + // initialize this control + arrow.src = options.arrow && options.arrow.image; + arrow.w = (options.arrow && options.arrow.width) || arrow.width(); + arrow.h = (options.arrow && options.arrow.height) || arrow.height(); + bar.w = (options.map && options.map.width) || bar.width(); + bar.h = (options.map && options.map.height) || bar.height(); + // bind mousedown event + // bar.bind('mousedown', mouseDown); + bar.addEventListener('mousedown', mouseDown); + bind.call(that, draw); + } +} diff --git a/src/editor/components/jgraduate/jQuery.jGraduate.js b/src/editor/components/jgraduate/jQuery.jGraduate.js index e6e09c8e..329069f0 100644 --- a/src/editor/components/jgraduate/jQuery.jGraduate.js +++ b/src/editor/components/jgraduate/jQuery.jGraduate.js @@ -155,6 +155,34 @@ function mkElem (name, attrs, newparent) { return elem; } +function deepExtend(out) { + out = out || {}; + + for (let i = 1, len = arguments.length; i < len; ++i) { + let obj = arguments[i]; + + if (!obj) { + continue; + } + + for (const key in obj) { + if (!obj.hasOwnProperty(key)) { + continue; + } + + // based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ + if (Object.prototype.toString.call(obj[key]) === '[object Object]') { + out[key] = deepExtend(out[key], obj[key]); + continue; + } + + out[key] = obj[key]; + } + } + + return out; +} + /** * @typedef {PlainObject} module:jGraduate.ColorOpac Object may have one or both values * @property {string} [color] #Hex color @@ -188,80 +216,76 @@ function mkElem (name, attrs, newparent) { * @returns {external:jQuery} */ export function jGraduateMethod (elem, options, okCallback, cancelCallback) { - return elem.each(function () { - const $this = $(this), - $settings = $.extend(true, {}, jGraduateDefaults, options || {}), - id = $this.attr('id'), - idref = '#' + $this.attr('id') + ' '; - // JFH !!!!! - const $shadowRoot = this.parentNode; - const $wc = (selector) => $($shadowRoot.querySelectorAll(selector)); + // return elem.each(function () { + const $this = elem, + $settings = $.extend(true, {}, jGraduateDefaults, options || {}), + id = $this.getAttribute('id'), + idref = '#' + $this.getAttribute('id') + ' '; + // JFH !!!!! + const $shadowRoot = elem.parentNode; + const $wc = (selector) => $($shadowRoot.querySelectorAll(selector)); - if (!idref) { - // eslint-disable-next-line no-alert - alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); - return; + if (!idref) { + // eslint-disable-next-line no-alert + alert('Container element must have an id attribute to maintain unique id strings for sub-elements.'); + return; + } + + const okClicked = function () { + switch ($this.paint.type) { + case 'radialGradient': + $this.paint.linearGradient = null; + break; + case 'linearGradient': + $this.paint.radialGradient = null; + break; + case 'solidColor': + $this.paint.radialGradient = $this.paint.linearGradient = null; + break; } + typeof $this.okCallback === 'function' && $this.okCallback($this.paint); + $this.hide(); + }; + const cancelClicked = function () { + typeof $this.cancelCallback === 'function' && $this.cancelCallback(); + $this.hide(); + }; - const okClicked = function () { - switch ($this.paint.type) { - case 'radialGradient': - $this.paint.linearGradient = null; - break; - case 'linearGradient': - $this.paint.radialGradient = null; - break; - case 'solidColor': - $this.paint.radialGradient = $this.paint.linearGradient = null; - break; - } - typeof $this.okCallback === 'function' && $this.okCallback($this.paint); - $this.hide(); - }; - const cancelClicked = function () { - typeof $this.cancelCallback === 'function' && $this.cancelCallback(); - $this.hide(); - }; - - $.extend( - true, - $this, - // public properties, methods, and callbacks - { - // make a copy of the incoming paint - paint: new jGraduate.Paint({copy: $settings.paint}), - okCallback: typeof okCallback === 'function' ? okCallback : null, - cancelCallback: typeof cancelCallback === 'function' ? cancelCallback : null - } - ); - - let // pos = $this.position(), - color = null; - const $win = $(window); - - if ($this.paint.type === 'none') { - $this.paint = new jGraduate.Paint({solidColor: 'ffffff'}); + $.extend( + true, + $this, + // public properties, methods, and callbacks + { + // make a copy of the incoming paint + paint: new jGraduate.Paint({copy: $settings.paint}), + okCallback: typeof okCallback === 'function' ? okCallback : null, + cancelCallback: typeof cancelCallback === 'function' ? cancelCallback : null } + ); - $this.addClass('jGraduate_Picker'); - /* eslint-disable max-len */ - $this.html( - '' + - '
' + - '
' + - '
' + - '
' - ); - /* JFH !!!! */ - const colPicker = $wc(idref + '> .jGraduate_colPick'); - const gradPicker = $wc(idref + '> .jGraduate_gradPick'); + let // pos = $this.position(), + color = null; + const $win = $(window); - gradPicker.html( - '
' + + if ($this.paint.type === 'none') { + $this.paint = new jGraduate.Paint({solidColor: 'ffffff'}); + } + $this.classList.add('jGraduate_Picker'); + // $this.addClass('jGraduate_Picker'); + /* eslint-disable max-len */ + $this.innerHTML = '' + + '
' + + '
' + + '
' + + '
'; + /* JFH !!!! */ + const colPicker = $this.querySelector('#jGraduate_colPick'); //($wc(idref + '> .jGraduate_colPick'))[0]; + const gradPicker = $this.querySelector('#jGraduate_gradPick'); // ($wc(idref + '> .jGraduate_gradPick'))[0]; + const html = '
' + '

' + $settings.window.pickerTitle + '

' + '
' + '
' + @@ -310,7 +334,7 @@ export function jGraduateMethod (elem, options, okCallback, cancelCallback) { '
' + '' + '
' + - '' + '' + '' + '' + @@ -350,891 +374,899 @@ export function jGraduateMethod (elem, options, okCallback, cancelCallback) { '
' + '' + '' + - '
' - ); - /* eslint-enable max-len */ - // -------------- - // Set up all the SVG elements (the gradient, stops and rectangle) - const MAX = 256, - MARGINX = 0, - MARGINY = 0, - // STOP_RADIUS = 15 / 2, - SIZEX = MAX - 2 * MARGINX, - SIZEY = MAX - 2 * MARGINY; + '
'; + const div = document.createElement('div'); + div.innerHTML = html; + while (div.children.length > 0) { + console.log(gradPicker); + gradPicker.appendChild(div.children[0]); + } + console.log(gradPicker); + /* eslint-enable max-len */ + // -------------- + // Set up all the SVG elements (the gradient, stops and rectangle) + const MAX = 256, + MARGINX = 0, + MARGINY = 0, + // STOP_RADIUS = 15 / 2, + SIZEX = MAX - 2 * MARGINX, + SIZEY = MAX - 2 * MARGINY; - const attrInput = {}; + const attrInput = {}; - const SLIDERW = 145; - $wc('.jGraduate_SliderBar').width(SLIDERW); - // JFH !!!!!! - const container = $wc('#' + id + '_jGraduate_GradContainer')[0]; + const SLIDERW = 145; + $wc('.jGraduate_SliderBar').width(SLIDERW); + // JFH !!!!!! + const container = $wc('#' + id + '_jGraduate_GradContainer')[0]; - const svg = mkElem('svg', { - id: id + '_jgraduate_svg', - width: MAX, - height: MAX, - xmlns: ns.svg - }, container); + const svg = mkElem('svg', { + id: id + '_jgraduate_svg', + width: MAX, + height: MAX, + xmlns: ns.svg + }, container); - // This wasn't working as designed - // let curType; - // curType = curType || $this.paint.type; + // This wasn't working as designed + // let curType; + // curType = curType || $this.paint.type; - // if we are sent a gradient, import it - let curType = $this.paint.type; + // if we are sent a gradient, import it + let curType = $this.paint.type; - let grad = $this.paint[curType]; - let curGradient = grad; + let grad = $this.paint[curType]; + let curGradient = grad; - const gradalpha = $this.paint.alpha; + const gradalpha = $this.paint.alpha; - const isSolid = curType === 'solidColor'; + const isSolid = curType === 'solidColor'; - // Make any missing gradients - switch (curType) { - case 'solidColor': - // fall through - case 'linearGradient': - if (!isSolid) { - curGradient.id = id + '_lg_jgraduate_grad'; - grad = curGradient = svg.appendChild(curGradient); - } - mkElem('radialGradient', { - id: id + '_rg_jgraduate_grad' - }, svg); - if (curType === 'linearGradient') { break; } - // fall through - case 'radialGradient': - if (!isSolid) { - curGradient.id = id + '_rg_jgraduate_grad'; - grad = curGradient = svg.appendChild(curGradient); - } - mkElem('linearGradient', { - id: id + '_lg_jgraduate_grad' - }, svg); + // Make any missing gradients + switch (curType) { + case 'solidColor': + // fall through + case 'linearGradient': + if (!isSolid) { + curGradient.id = id + '_lg_jgraduate_grad'; + grad = curGradient = svg.appendChild(curGradient); } - - let stopGroup; // eslint-disable-line prefer-const - if (isSolid) { - // JFH !!!!!!!! - grad = curGradient = $wc('#' + id + '_lg_jgraduate_grad')[0]; - color = $this.paint[curType]; - mkStop(0, '#' + color, 1); - - const type = typeof $settings.newstop; - - if (type === 'string') { - switch ($settings.newstop) { - case 'same': - mkStop(1, '#' + color, 1); - break; - - case 'inverse': { - // Invert current color for second stop - let inverted = ''; - for (let i = 0; i < 6; i += 2) { - // const ch = color.substr(i, 2); - let inv = (255 - Number.parseInt(color.substr(i, 2), 16)).toString(16); - if (inv.length < 2) inv = 0 + inv; - inverted += inv; - } - mkStop(1, '#' + inverted, 1); - break; - } case 'white': - mkStop(1, '#ffffff', 1); - break; - - case 'black': - mkStop(1, '#000000', 1); - break; - } - } else if (type === 'object') { - const opac = ('opac' in $settings.newstop) ? $settings.newstop.opac : 1; - mkStop(1, ($settings.newstop.color || '#' + color), opac); - } - } - - const x1 = Number.parseFloat(grad.getAttribute('x1') || 0.0), - y1 = Number.parseFloat(grad.getAttribute('y1') || 0.0), - x2 = Number.parseFloat(grad.getAttribute('x2') || 1.0), - y2 = Number.parseFloat(grad.getAttribute('y2') || 0.0); - - const cx = Number.parseFloat(grad.getAttribute('cx') || 0.5), - cy = Number.parseFloat(grad.getAttribute('cy') || 0.5), - fx = Number.parseFloat(grad.getAttribute('fx') || cx), - fy = Number.parseFloat(grad.getAttribute('fy') || cy); - - const previewRect = mkElem('rect', { - id: id + '_jgraduate_rect', - x: MARGINX, - y: MARGINY, - width: SIZEX, - height: SIZEY, - fill: 'url(#' + id + '_jgraduate_grad)', - 'fill-opacity': gradalpha / 100 + mkElem('radialGradient', { + id: id + '_rg_jgraduate_grad' }, svg); + if (curType === 'linearGradient') { break; } + // fall through + case 'radialGradient': + if (!isSolid) { + curGradient.id = id + '_rg_jgraduate_grad'; + grad = curGradient = svg.appendChild(curGradient); + } + mkElem('linearGradient', { + id: id + '_lg_jgraduate_grad' + }, svg); + } - // stop visuals created here - const beginCoord = $('
').attr({ - class: 'grad_coord jGraduate_lg_field', - title: 'Begin Stop' - }).text(1).css({ - top: y1 * MAX, - left: x1 * MAX - }).data('coord', 'start').appendTo(container); + let stopGroup; // eslint-disable-line prefer-const + if (isSolid) { + // JFH !!!!!!!! + grad = curGradient = $wc('#' + id + '_lg_jgraduate_grad')[0]; + color = $this.paint[curType]; + mkStop(0, '#' + color, 1); - const endCoord = beginCoord.clone().text(2).css({ - top: y2 * MAX, - left: x2 * MAX - }).attr('title', 'End stop').data('coord', 'end').appendTo(container); + const type = typeof $settings.newstop; - const centerCoord = $('
').attr({ - class: 'grad_coord jGraduate_rg_field', - title: 'Center stop' - }).text('C').css({ - top: cy * MAX, - left: cx * MAX - }).data('coord', 'center').appendTo(container); + if (type === 'string') { + switch ($settings.newstop) { + case 'same': + mkStop(1, '#' + color, 1); + break; - const focusCoord = centerCoord.clone().text('F').css({ - top: fy * MAX, - left: fx * MAX, - display: 'none' - }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container); - - focusCoord[0].id = id + '_jGraduate_focusCoord'; - - let showFocus; - $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function (i, attr) { - const isRadial = isNaN(attr[1]); - - let attrval = curGradient.getAttribute(attr); - if (!attrval) { - // Set defaults - if (isRadial) { - // For radial points - attrval = '0.5'; - } else { - // Only x2 is 1 - attrval = attr === 'x2' ? '1.0' : '0.0'; + case 'inverse': { + // Invert current color for second stop + let inverted = ''; + for (let i = 0; i < 6; i += 2) { + // const ch = color.substr(i, 2); + let inv = (255 - Number.parseInt(color.substr(i, 2), 16)).toString(16); + if (inv.length < 2) inv = 0 + inv; + inverted += inv; } + mkStop(1, '#' + inverted, 1); + break; + } case 'white': + mkStop(1, '#ffffff', 1); + break; + + case 'black': + mkStop(1, '#000000', 1); + break; } + } else if (type === 'object') { + const opac = ('opac' in $settings.newstop) ? $settings.newstop.opac : 1; + mkStop(1, ($settings.newstop.color || '#' + color), opac); + } + } - attrInput[attr] = $wc('#' + id + '_jGraduate_' + attr) - .val(attrval) - .change(function () { - // TODO: Support values < 0 and > 1 (zoomable preview?) - if (isNaN(Number.parseFloat(this.value)) || this.value < 0) { - this.value = 0.0; - } else if (this.value > 1) { - this.value = 1.0; - } + const x1 = Number.parseFloat(grad.getAttribute('x1') || 0.0), + y1 = Number.parseFloat(grad.getAttribute('y1') || 0.0), + x2 = Number.parseFloat(grad.getAttribute('x2') || 1.0), + y2 = Number.parseFloat(grad.getAttribute('y2') || 0.0); - if (!(attr[0] === 'f' && - !showFocus) && - ((isRadial && curType === 'radialGradient') || (!isRadial && curType === 'linearGradient'))) { - curGradient.setAttribute(attr, this.value); - } + const cx = Number.parseFloat(grad.getAttribute('cx') || 0.5), + cy = Number.parseFloat(grad.getAttribute('cy') || 0.5), + fx = Number.parseFloat(grad.getAttribute('fx') || cx), + fy = Number.parseFloat(grad.getAttribute('fy') || cy); - const $elem = isRadial - ? attr[0] === 'c' ? centerCoord : focusCoord - : attr[1] === '1' ? beginCoord : endCoord; + const previewRect = mkElem('rect', { + id: id + '_jgraduate_rect', + x: MARGINX, + y: MARGINY, + width: SIZEX, + height: SIZEY, + fill: 'url(#' + id + '_jgraduate_grad)', + 'fill-opacity': gradalpha / 100 + }, svg); - const cssName = attr.includes('x') ? 'left' : 'top'; + // stop visuals created here + const beginCoord = $('
').attr({ + class: 'grad_coord jGraduate_lg_field', + title: 'Begin Stop' + }).text(1).css({ + top: y1 * MAX, + left: x1 * MAX + }).data('coord', 'start').appendTo(container); - $elem.css(cssName, this.value * MAX); - }).change(); - }); + const endCoord = beginCoord.clone().text(2).css({ + top: y2 * MAX, + left: x2 * MAX + }).attr('title', 'End stop').data('coord', 'end').appendTo(container); - /** - * - * @param {Float} n - * @param {Float|string} colr - * @param {Float} opac - * @param {boolean} [sel] - * @param {SVGStopElement} [stopElem] - * @returns {SVGStopElement} - */ - function mkStop (n, colr, opac, sel, stopElem) { - const stop = stopElem || mkElem('stop', { - 'stop-color': colr, - 'stop-opacity': opac, - offset: n - }, curGradient); - if (stopElem) { - colr = stopElem.getAttribute('stop-color'); - opac = stopElem.getAttribute('stop-opacity'); - n = stopElem.getAttribute('offset'); + const centerCoord = $('
').attr({ + class: 'grad_coord jGraduate_rg_field', + title: 'Center stop' + }).text('C').css({ + top: cy * MAX, + left: cx * MAX + }).data('coord', 'center').appendTo(container); + + const focusCoord = centerCoord.clone().text('F').css({ + top: fy * MAX, + left: fx * MAX, + display: 'none' + }).attr('title', 'Focus point').data('coord', 'focus').appendTo(container); + + focusCoord[0].id = id + '_jGraduate_focusCoord'; + + let showFocus; + $.each(['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'], function (i, attr) { + const isRadial = isNaN(attr[1]); + + let attrval = curGradient.getAttribute(attr); + if (!attrval) { + // Set defaults + if (isRadial) { + // For radial points + attrval = '0.5'; } else { - curGradient.append(stop); + // Only x2 is 1 + attrval = attr === 'x2' ? '1.0' : '0.0'; } - if (opac === null) opac = 1; + } - const pickerD = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,' + - '3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,' + - '2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z'; - - const pathbg = mkElem('path', { - d: pickerD, - fill: 'url(#jGraduate_trans)', - transform: 'translate(' + (10 + n * MAX) + ', 26)' - }, stopGroup); - - const path = mkElem('path', { - d: pickerD, - fill: colr, - 'fill-opacity': opac, - transform: 'translate(' + (10 + n * MAX) + ', 26)', - stroke: '#000', - 'stroke-width': 1.5 - }, stopGroup); - - $(path).mousedown(function (e) { - selectStop(this); - drag = curStop; - $win.mousemove(dragColor).mouseup(remDrags); - stopOffset = stopMakerDiv.offset(); - e.preventDefault(); - return false; - }).data('stop', stop).data('bg', pathbg).dblclick(function () { - $wc('div.jGraduate_LightBox').show(); - const colorhandle = this; - let stopOpacity = Number(stop.getAttribute('stop-opacity')) || 1; - let stopColor = stop.getAttribute('stop-color') || 1; - let thisAlpha = (Number.parseFloat(stopOpacity) * 255).toString(16); - while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } - colr = stopColor.substr(1) + thisAlpha; - jPickerMethod($wc('#' + id + '_jGraduate_stopPicker').css({left: 100, bottom: 15}), { - window: {title: 'Pick the start color and opacity for the gradient'}, - images: {clientPath: $settings.images.clientPath}, - color: {active: colr, alphaSupport: true} - }, function (clr, arg2) { - stopColor = clr.val('hex') ? ('#' + clr.val('hex')) : 'none'; - stopOpacity = clr.val('a') !== null ? clr.val('a') / 256 : 1; - colorhandle.setAttribute('fill', stopColor); - colorhandle.setAttribute('fill-opacity', stopOpacity); - stop.setAttribute('stop-color', stopColor); - stop.setAttribute('stop-opacity', stopOpacity); - $wc('div.jGraduate_LightBox').hide(); - $wc('#' + id + '_jGraduate_stopPicker').hide(); - }, null, function () { - $wc('div.jGraduate_LightBox').hide(); - $wc('#' + id + '_jGraduate_stopPicker').hide(); - }); - }); - - $(curGradient).find('stop').each(function () { - const curS = $(this); - if (Number(this.getAttribute('offset')) > n) { - if (!colr) { - const newcolor = this.getAttribute('stop-color'); - const newopac = this.getAttribute('stop-opacity'); - stop.setAttribute('stop-color', newcolor); - path.setAttribute('fill', newcolor); - stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac); - path.setAttribute('fill-opacity', newopac === null ? 1 : newopac); - } - curS.before(stop); - return false; + attrInput[attr] = $wc('#' + id + '_jGraduate_' + attr) + .val(attrval) + .change(function () { + // TODO: Support values < 0 and > 1 (zoomable preview?) + if (isNaN(Number.parseFloat(this.value)) || this.value < 0) { + this.value = 0.0; + } else if (this.value > 1) { + this.value = 1.0; } - return true; - }); - if (sel) selectStop(path); - return stop; - } - /** - * - * @returns {void} - */ - function remStop () { - delStop.setAttribute('display', 'none'); - const path = $wc(curStop); - const stop = path.data('stop'); - const bg = path.data('bg'); - $([curStop, stop, bg]).remove(); - } - - const stopMakerDiv = $wc('#' + id + '_jGraduate_StopSlider'); - - let stops, curStop, drag; - - const delStop = mkElem('path', { - d: 'm9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5', - fill: 'none', - stroke: '#D00', - 'stroke-width': 5, - display: 'none' - }, undefined); // stopMakerSVG); - - /** - * @param {Element} item - * @returns {void} - */ - function selectStop (item) { - if (curStop) curStop.setAttribute('stroke', '#000'); - item.setAttribute('stroke', 'blue'); - curStop = item; - } - - let stopOffset; - - /** - * - * @returns {void} - */ - function remDrags () { - $win.unbind('mousemove', dragColor); - if (delStop.getAttribute('display') !== 'none') { - remStop(); - } - drag = null; - } - - let scaleX = 1, scaleY = 1, angle = 0; - - let cX = cx; - let cY = cy; - /** - * - * @returns {void} - */ - function xform () { - const rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : ''; - if (scaleX === 1 && scaleY === 1) { - curGradient.removeAttribute('gradientTransform'); - // $wc('#ang').addClass('dis'); - } else { - const x = -cX * (scaleX - 1); - const y = -cY * (scaleY - 1); - curGradient.setAttribute( - 'gradientTransform', - rot + 'translate(' + x + ',' + y + ') scale(' + - scaleX + ',' + scaleY + ')' - ); - // $wc('#ang').removeClass('dis'); - } - } - - /** - * @param {Event} evt - * @returns {void} - */ - function dragColor (evt) { - let x = evt.pageX - stopOffset.left; - const y = evt.pageY - stopOffset.top; - x = x < 10 - ? 10 - : x > MAX + 10 - ? MAX + 10 - : x; - - const xfStr = 'translate(' + x + ', 26)'; - if (y < -60 || y > 130) { - delStop.setAttribute('display', 'block'); - delStop.setAttribute('transform', xfStr); - } else { - delStop.setAttribute('display', 'none'); - } - - drag.setAttribute('transform', xfStr); - $.data(drag, 'bg').setAttribute('transform', xfStr); - const stop = $.data(drag, 'stop'); - const sX = (x - 10) / MAX; - - stop.setAttribute('offset', sX); - - let last = 0; - $(curGradient).find('stop').each(function (i) { - const cur = this.getAttribute('offset'); - const t = $(this); - if (cur < last) { - t.prev().before(t); - stops = $(curGradient).find('stop'); + if (!(attr[0] === 'f' && + !showFocus) && + ((isRadial && curType === 'radialGradient') || (!isRadial && curType === 'linearGradient'))) { + curGradient.setAttribute(attr, this.value); } - last = cur; - }); + + const $elem = isRadial + ? attr[0] === 'c' ? centerCoord : focusCoord + : attr[1] === '1' ? beginCoord : endCoord; + + const cssName = attr.includes('x') ? 'left' : 'top'; + + $elem.css(cssName, this.value * MAX); + }).change(); + }); + + /** + * + * @param {Float} n + * @param {Float|string} colr + * @param {Float} opac + * @param {boolean} [sel] + * @param {SVGStopElement} [stopElem] + * @returns {SVGStopElement} + */ + function mkStop (n, colr, opac, sel, stopElem) { + const stop = stopElem || mkElem('stop', { + 'stop-color': colr, + 'stop-opacity': opac, + offset: n + }, curGradient); + if (stopElem) { + colr = stopElem.getAttribute('stop-color'); + opac = stopElem.getAttribute('stop-opacity'); + n = stopElem.getAttribute('offset'); + } else { + console.log(curGradient); + curGradient.appendChild(stop); } + if (opac === null) opac = 1; - const stopMakerSVG = mkElem('svg', { - width: '100%', - height: 45 - }, stopMakerDiv[0]); + const pickerD = 'M-6.2,0.9c3.6-4,6.7-4.3,6.7-12.4c-0.2,7.9,' + + '3.1,8.8,6.5,12.4c3.5,3.8,2.9,9.6,0,12.3c-3.1,2.8-10.4,' + + '2.7-13.2,0C-9.6,9.9-9.4,4.4-6.2,0.9z'; - const transPattern = mkElem('pattern', { - width: 16, - height: 16, - patternUnits: 'userSpaceOnUse', - id: 'jGraduate_trans' - }, stopMakerSVG); + const pathbg = mkElem('path', { + d: pickerD, + fill: 'url(#jGraduate_trans)', + transform: 'translate(' + (10 + n * MAX) + ', 26)' + }, stopGroup); - const transImg = mkElem('image', { - width: 16, - height: 16 - }, transPattern); + const path = mkElem('path', { + d: pickerD, + fill: colr, + 'fill-opacity': opac, + transform: 'translate(' + (10 + n * MAX) + ', 26)', + stroke: '#000', + 'stroke-width': 1.5 + }, stopGroup); - const bgImage = $settings.images.clientPath + 'map-opacity.png'; - - transImg.setAttributeNS(ns.xlink, 'xlink:href', bgImage); - - $(stopMakerSVG).click(function (evt) { + $(path).mousedown(function (e) { + selectStop(this); + drag = curStop; + $win.mousemove(dragColor).mouseup(remDrags); stopOffset = stopMakerDiv.offset(); - const {target} = evt; - if (target.tagName === 'path') return; - let x = evt.pageX - stopOffset.left - 8; - x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; - mkStop(x / MAX, 0, 0, true); - evt.stopPropagation(); + e.preventDefault(); + return false; + }).data('stop', stop).data('bg', pathbg).dblclick(function () { + $wc('div.jGraduate_LightBox').show(); + const colorhandle = this; + let stopOpacity = Number(stop.getAttribute('stop-opacity')) || 1; + let stopColor = stop.getAttribute('stop-color') || 1; + let thisAlpha = (Number.parseFloat(stopOpacity) * 255).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } + colr = stopColor.substr(1) + thisAlpha; + jPickerMethod($wc('#' + id + '_jGraduate_stopPicker').css({left: 100, bottom: 15}), { + window: {title: 'Pick the start color and opacity for the gradient'}, + images: {clientPath: $settings.images.clientPath}, + color: {active: colr, alphaSupport: true} + }, function (clr, arg2) { + stopColor = clr.val('hex') ? ('#' + clr.val('hex')) : 'none'; + stopOpacity = clr.val('a') !== null ? clr.val('a') / 256 : 1; + colorhandle.setAttribute('fill', stopColor); + colorhandle.setAttribute('fill-opacity', stopOpacity); + stop.setAttribute('stop-color', stopColor); + stop.setAttribute('stop-opacity', stopOpacity); + $wc('div.jGraduate_LightBox').hide(); + $wc('#' + id + '_jGraduate_stopPicker').hide(); + }, null, function () { + $wc('div.jGraduate_LightBox').hide(); + $wc('#' + id + '_jGraduate_stopPicker').hide(); + }); }); - $(stopMakerSVG).mouseover(function () { - stopMakerSVG.append(delStop); - }); - - stopGroup = mkElem('g', {}, stopMakerSVG); - - mkElem('line', { - x1: 10, - y1: 15, - x2: MAX + 10, - y2: 15, - 'stroke-width': 2, - stroke: '#000' - }, stopMakerSVG); - - const spreadMethodOpt = gradPicker.find('.jGraduate_spreadMethod').change(function () { - curGradient.setAttribute('spreadMethod', $(this).val()); - }); - - // handle dragging the stop around the swatch - let draggingCoord = null; - - const onCoordDrag = function (evt) { - let x = evt.pageX - offset.left; - let y = evt.pageY - offset.top; - - // clamp stop to the swatch - x = x < 0 ? 0 : x > MAX ? MAX : x; - y = y < 0 ? 0 : y > MAX ? MAX : y; - - draggingCoord.css('left', x).css('top', y); - - // calculate stop offset - const fracx = x / SIZEX; - const fracy = y / SIZEY; - - const type = draggingCoord.data('coord'); - const grd = curGradient; - - switch (type) { - case 'start': - attrInput.x1.val(fracx); - attrInput.y1.val(fracy); - grd.setAttribute('x1', fracx); - grd.setAttribute('y1', fracy); - break; - case 'end': - attrInput.x2.val(fracx); - attrInput.y2.val(fracy); - grd.setAttribute('x2', fracx); - grd.setAttribute('y2', fracy); - break; - case 'center': - attrInput.cx.val(fracx); - attrInput.cy.val(fracy); - grd.setAttribute('cx', fracx); - grd.setAttribute('cy', fracy); - cX = fracx; - cY = fracy; - xform(); - break; - case 'focus': - attrInput.fx.val(fracx); - attrInput.fy.val(fracy); - grd.setAttribute('fx', fracx); - grd.setAttribute('fy', fracy); - xform(); + $(curGradient).find('stop').each(function () { + const curS = $(this); + if (Number(this.getAttribute('offset')) > n) { + if (!colr) { + const newcolor = this.getAttribute('stop-color'); + const newopac = this.getAttribute('stop-opacity'); + stop.setAttribute('stop-color', newcolor); + path.setAttribute('fill', newcolor); + stop.setAttribute('stop-opacity', newopac === null ? 1 : newopac); + path.setAttribute('fill-opacity', newopac === null ? 1 : newopac); + } + curS.before(stop); + return false; } + return true; + }); + if (sel) selectStop(path); + return stop; + } - evt.preventDefault(); - }; + /** + * + * @returns {void} + */ + function remStop () { + delStop.setAttribute('display', 'none'); + const path = $wc(curStop); + const stop = path.data('stop'); + const bg = path.data('bg'); + $([curStop, stop, bg]).remove(); + } - const onCoordUp = function () { - draggingCoord = null; - $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp); - }; + const stopMakerDiv = $wc('#' + id + '_jGraduate_StopSlider'); - // Linear gradient - // (function () { + let stops, curStop, drag; + const delStop = mkElem('path', { + d: 'm9.75,-6l-19.5,19.5m0,-19.5l19.5,19.5', + fill: 'none', + stroke: '#D00', + 'stroke-width': 5, + display: 'none' + }, undefined); // stopMakerSVG); + + /** + * @param {Element} item + * @returns {void} + */ + function selectStop (item) { + if (curStop) curStop.setAttribute('stroke', '#000'); + item.setAttribute('stroke', 'blue'); + curStop = item; + } + + let stopOffset; + + /** + * + * @returns {void} + */ + function remDrags () { + $win.unbind('mousemove', dragColor); + if (delStop.getAttribute('display') !== 'none') { + remStop(); + } + drag = null; + } + + let scaleX = 1, scaleY = 1, angle = 0; + + let cX = cx; + let cY = cy; + /** + * + * @returns {void} + */ + function xform () { + const rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : ''; + if (scaleX === 1 && scaleY === 1) { + curGradient.removeAttribute('gradientTransform'); + // $wc('#ang').addClass('dis'); + } else { + const x = -cX * (scaleX - 1); + const y = -cY * (scaleY - 1); + curGradient.setAttribute( + 'gradientTransform', + rot + 'translate(' + x + ',' + y + ') scale(' + + scaleX + ',' + scaleY + ')' + ); + // $wc('#ang').removeClass('dis'); + } + } + + /** + * @param {Event} evt + * @returns {void} + */ + function dragColor (evt) { + let x = evt.pageX - stopOffset.left; + const y = evt.pageY - stopOffset.top; + x = x < 10 + ? 10 + : x > MAX + 10 + ? MAX + 10 + : x; + + const xfStr = 'translate(' + x + ', 26)'; + if (y < -60 || y > 130) { + delStop.setAttribute('display', 'block'); + delStop.setAttribute('transform', xfStr); + } else { + delStop.setAttribute('display', 'none'); + } + + drag.setAttribute('transform', xfStr); + $.data(drag, 'bg').setAttribute('transform', xfStr); + const stop = $.data(drag, 'stop'); + const sX = (x - 10) / MAX; + + stop.setAttribute('offset', sX); + + let last = 0; + $(curGradient).find('stop').each(function (i) { + const cur = this.getAttribute('offset'); + const t = $(this); + if (cur < last) { + t.prev().before(t); + stops = $(curGradient).find('stop'); + } + last = cur; + }); + } + + const stopMakerSVG = mkElem('svg', { + width: '100%', + height: 45 + }, stopMakerDiv[0]); + + const transPattern = mkElem('pattern', { + width: 16, + height: 16, + patternUnits: 'userSpaceOnUse', + id: 'jGraduate_trans' + }, stopMakerSVG); + + const transImg = mkElem('image', { + width: 16, + height: 16 + }, transPattern); + + const bgImage = $settings.images.clientPath + 'map-opacity.png'; + + transImg.setAttributeNS(ns.xlink, 'xlink:href', bgImage); + + $(stopMakerSVG).click(function (evt) { + stopOffset = stopMakerDiv.offset(); + const {target} = evt; + if (target.tagName === 'path') return; + let x = evt.pageX - stopOffset.left - 8; + x = x < 10 ? 10 : x > MAX + 10 ? MAX + 10 : x; + mkStop(x / MAX, 0, 0, true); + evt.stopPropagation(); + }); + + $(stopMakerSVG).mouseover(function () { + stopMakerSVG.append(delStop); + }); + + stopGroup = mkElem('g', {}, stopMakerSVG); + + mkElem('line', { + x1: 10, + y1: 15, + x2: MAX + 10, + y2: 15, + 'stroke-width': 2, + stroke: '#000' + }, stopMakerSVG); + const spreadMethodOpt = gradPicker.querySelector('#jGraduate_spreadMethod'); + spreadMethodOpt.addEventListener('change', function () { + curGradient.setAttribute('spreadMethod', this.value); + }); + + // handle dragging the stop around the swatch + let draggingCoord = null; + + const onCoordDrag = function (evt) { + let x = evt.pageX - offset.left; + let y = evt.pageY - offset.top; + + // clamp stop to the swatch + x = x < 0 ? 0 : x > MAX ? MAX : x; + y = y < 0 ? 0 : y > MAX ? MAX : y; + + draggingCoord.css('left', x).css('top', y); + + // calculate stop offset + const fracx = x / SIZEX; + const fracy = y / SIZEY; + + const type = draggingCoord.data('coord'); + const grd = curGradient; + + switch (type) { + case 'start': + attrInput.x1.val(fracx); + attrInput.y1.val(fracy); + grd.setAttribute('x1', fracx); + grd.setAttribute('y1', fracy); + break; + case 'end': + attrInput.x2.val(fracx); + attrInput.y2.val(fracy); + grd.setAttribute('x2', fracx); + grd.setAttribute('y2', fracy); + break; + case 'center': + attrInput.cx.val(fracx); + attrInput.cy.val(fracy); + grd.setAttribute('cx', fracx); + grd.setAttribute('cy', fracy); + cX = fracx; + cY = fracy; + xform(); + break; + case 'focus': + attrInput.fx.val(fracx); + attrInput.fy.val(fracy); + grd.setAttribute('fx', fracx); + grd.setAttribute('fy', fracy); + xform(); + } + + evt.preventDefault(); + }; + + const onCoordUp = function () { + draggingCoord = null; + $win.unbind('mousemove', onCoordDrag).unbind('mouseup', onCoordUp); + }; + + // Linear gradient + // (function () { + + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + + let numstops = stops.length; + // if there are not at least two stops, then + if (numstops < 2) { + while (numstops < 2) { + curGradient.append(document.createElementNS(ns.svg, 'stop')); + ++numstops; + } stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + } - let numstops = stops.length; - // if there are not at least two stops, then - if (numstops < 2) { - while (numstops < 2) { - curGradient.append(document.createElementNS(ns.svg, 'stop')); - ++numstops; - } - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - } + for (let i = 0; i < numstops; i++) { + mkStop(0, 0, 0, 0, stops[i]); + } - for (let i = 0; i < numstops; i++) { - mkStop(0, 0, 0, 0, stops[i]); - } + spreadMethodOpt.setAttribute('value', curGradient.getAttribute('spreadMethod') || 'pad'); - spreadMethodOpt.val(curGradient.getAttribute('spreadMethod') || 'pad'); + let offset; - let offset; + // No match, so show focus point + showFocus = false; - // No match, so show focus point - showFocus = false; + previewRect.setAttribute('fill-opacity', gradalpha / 100); - previewRect.setAttribute('fill-opacity', gradalpha / 100); + $wc('#' + id + ' div.grad_coord').mousedown(function (evt) { + evt.preventDefault(); + draggingCoord = $(this); + // const sPos = draggingCoord.offset(); + offset = draggingCoord.parent().offset(); + $win.mousemove(onCoordDrag).mouseup(onCoordUp); + }); - $wc('#' + id + ' div.grad_coord').mousedown(function (evt) { - evt.preventDefault(); - draggingCoord = $(this); - // const sPos = draggingCoord.offset(); - offset = draggingCoord.parent().offset(); - $win.mousemove(onCoordDrag).mouseup(onCoordUp); - }); + // bind GUI elements + $wc('#' + id + '_jGraduate_Ok').bind('click', function () { + $this.paint.type = curType; + $this.paint[curType] = curGradient.cloneNode(true); + $this.paint.solidColor = null; + okClicked(); + }); + $wc('#' + id + '_jGraduate_Cancel').bind('click', function (paint) { + cancelClicked(); + }); - // bind GUI elements - $wc('#' + id + '_jGraduate_Ok').bind('click', function () { - $this.paint.type = curType; - $this.paint[curType] = curGradient.cloneNode(true); - $this.paint.solidColor = null; - okClicked(); - }); - $wc('#' + id + '_jGraduate_Cancel').bind('click', function (paint) { - cancelClicked(); - }); - - if (curType === 'radialGradient') { - if (showFocus) { - focusCoord.show(); - } else { - focusCoord.hide(); - attrInput.fx.val(''); - attrInput.fy.val(''); - } - } - - $wc('#' + id + '_jGraduate_match_ctr')[0].checked = !showFocus; - - let lastfx, lastfy; - - $wc('#' + id + '_jGraduate_match_ctr').change(function () { - showFocus = !this.checked; - focusCoord.toggle(showFocus); + if (curType === 'radialGradient') { + if (showFocus) { + focusCoord.show(); + } else { + focusCoord.hide(); attrInput.fx.val(''); attrInput.fy.val(''); - const grd = curGradient; - if (!showFocus) { - lastfx = grd.getAttribute('fx'); - lastfy = grd.getAttribute('fy'); - grd.removeAttribute('fx'); - grd.removeAttribute('fy'); - } else { - const fX = lastfx || 0.5; - const fY = lastfy || 0.5; - grd.setAttribute('fx', fX); - grd.setAttribute('fy', fY); - attrInput.fx.val(fX); - attrInput.fy.val(fY); - } - }); - - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); - numstops = stops.length; - // if there are not at least two stops, then - if (numstops < 2) { - while (numstops < 2) { - curGradient.append(document.createElementNS(ns.svg, 'stop')); - ++numstops; - } - stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); } + } - let slider; + $wc('#' + id + '_jGraduate_match_ctr')[0].checked = !showFocus; - const setSlider = function (e) { - const {offset: {left}} = slider; - const div = slider.parent; - let x = (e.pageX - left - Number.parseInt(div.css('border-left-width'))); - if (x > SLIDERW) x = SLIDERW; - if (x <= 0) x = 0; - const posx = x - 5; - x /= SLIDERW; + let lastfx, lastfy; - switch (slider.type) { - case 'radius': - x = (x * 2) ** 2.5; - if (x > 0.98 && x < 1.02) x = 1; - if (x <= 0.01) x = 0.01; - curGradient.setAttribute('r', x); - break; - case 'opacity': - $this.paint.alpha = Number.parseInt(x * 100); - previewRect.setAttribute('fill-opacity', x); - break; - case 'ellip': - scaleX = 1; - scaleY = 1; - if (x < 0.5) { - x /= 0.5; // 0.001 - scaleX = x <= 0 ? 0.01 : x; - } else if (x > 0.5) { - x /= 0.5; // 2 - x = 2 - x; - scaleY = x <= 0 ? 0.01 : x; - } - xform(); - x -= 1; - if (scaleY === x + 1) { - x = Math.abs(x); - } - break; - case 'angle': - x -= 0.5; - angle = x *= 180; - xform(); - x /= 100; - break; - } - slider.elem.css({'margin-left': posx}); - x = Math.round(x * 100); - slider.input.val(x); - }; - - let ellipVal = 0, angleVal = 0; - - if (curType === 'radialGradient') { - const tlist = curGradient.gradientTransform.baseVal; - if (tlist.numberOfItems === 2) { - const t = tlist.getItem(0); - const s = tlist.getItem(1); - if (t.type === 2 && s.type === 3) { - const m = s.matrix; - if (m.a !== 1) { - ellipVal = Math.round(-(1 - m.a) * 100); - } else if (m.d !== 1) { - ellipVal = Math.round((1 - m.d) * 100); - } - } - } else if (tlist.numberOfItems === 3) { - // Assume [R][T][S] - const r = tlist.getItem(0); - const t = tlist.getItem(1); - const s = tlist.getItem(2); - - if (r.type === 4 && - t.type === 2 && - s.type === 3 - ) { - angleVal = Math.round(r.angle); - const m = s.matrix; - if (m.a !== 1) { - ellipVal = Math.round(-(1 - m.a) * 100); - } else if (m.d !== 1) { - ellipVal = Math.round((1 - m.d) * 100); - } - } - } + $wc('#' + id + '_jGraduate_match_ctr').change(function () { + showFocus = !this.checked; + focusCoord.toggle(showFocus); + attrInput.fx.val(''); + attrInput.fy.val(''); + const grd = curGradient; + if (!showFocus) { + lastfx = grd.getAttribute('fx'); + lastfy = grd.getAttribute('fy'); + grd.removeAttribute('fx'); + grd.removeAttribute('fy'); + } else { + const fX = lastfx || 0.5; + const fY = lastfy || 0.5; + grd.setAttribute('fx', fX); + grd.setAttribute('fy', fY); + attrInput.fx.val(fX); + attrInput.fy.val(fY); } - - const sliders = { - radius: { - handle: '#' + id + '_jGraduate_RadiusArrows', - input: '#' + id + '_jGraduate_RadiusInput', - val: (curGradient.getAttribute('r') || 0.5) * 100 - }, - opacity: { - handle: '#' + id + '_jGraduate_OpacArrows', - input: '#' + id + '_jGraduate_OpacInput', - val: $this.paint.alpha || 100 - }, - ellip: { - handle: '#' + id + '_jGraduate_EllipArrows', - input: '#' + id + '_jGraduate_EllipInput', - val: ellipVal - }, - angle: { - handle: '#' + id + '_jGraduate_AngleArrows', - input: '#' + id + '_jGraduate_AngleInput', - val: angleVal - } - }; - - $.each(sliders, function (type, data) { - const handle = $(data.handle); - handle.mousedown(function (evt) { - const parent = handle.parent(); - slider = { - type, - elem: handle, - input: $(data.input), - parent, - offset: parent.offset() - }; - $win.mousemove(dragSlider).mouseup(stopSlider); - evt.preventDefault(); - }); - - $(data.input).val(data.val).change(function () { - const isRad = curType === 'radialGradient'; - let val = Number(this.value); - let xpos = 0; - switch (type) { - case 'radius': - if (isRad) curGradient.setAttribute('r', val / 100); - xpos = (((val / 100) ** (1 / 2.5)) / 2) * SLIDERW; - break; - - case 'opacity': - $this.paint.alpha = val; - previewRect.setAttribute('fill-opacity', val / 100); - xpos = val * (SLIDERW / 100); - break; - - case 'ellip': - scaleX = scaleY = 1; - if (val === 0) { - xpos = SLIDERW * 0.5; - break; - } - if (val > 99.5) val = 99.5; - if (val > 0) { - scaleY = 1 - (val / 100); - } else { - scaleX = -(val / 100) - 1; - } - - xpos = SLIDERW * ((val + 100) / 2) / 100; - if (isRad) xform(); - break; - - case 'angle': - angle = val; - xpos = angle / 180; - xpos += 0.5; - xpos *= SLIDERW; - if (isRad) xform(); - } - if (xpos > SLIDERW) { - xpos = SLIDERW; - } else if (xpos < 0) { - xpos = 0; - } - handle.css({'margin-left': xpos - 5}); - }).change(); - }); - - const dragSlider = function (evt) { - setSlider(evt); - evt.preventDefault(); - }; - - const stopSlider = function (evt) { - $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider); - slider = null; - }; - - // -------------- - let thisAlpha = ($this.paint.alpha * 255 / 100).toString(16); - while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } - thisAlpha = thisAlpha.split('.')[0]; - color = $this.paint.solidColor === 'none' ? '' : $this.paint.solidColor + thisAlpha; - - if (!isSolid) { - color = stops[0].getAttribute('stop-color'); - } - - // This should be done somewhere else, probably - $.extend(jPickerDefaults.window, { - alphaSupport: true, effects: {type: 'show', speed: 0} - }); - - jPickerMethod(colPicker, - { - window: {title: $settings.window.pickerTitle}, - images: {clientPath: $settings.images.clientPath}, - color: {active: color, alphaSupport: true} - }, - function (clr) { - $this.paint.type = 'solidColor'; - $this.paint.alpha = clr.val('ahex') ? Math.round((clr.val('a') / 255) * 100) : 100; - $this.paint.solidColor = clr.val('hex') ? clr.val('hex') : 'none'; - $this.paint.radialGradient = null; - okClicked(); - }, - null, - function () { cancelClicked(); } - ); - // JFH !!!! - // const tabs = $wc(idref + ' .jGraduate_tabs li'); - const tabs = $wc('.jGraduate_tabs li'); - tabs.click(function () { - tabs.removeClass('jGraduate_tab_current'); - $(this).addClass('jGraduate_tab_current'); - $wc(idref + ' > div').hide(); - const type = $(this).attr('data-type'); - $wc(idref + ' .jGraduate_gradPick').show(); - if (type === 'rg' || type === 'lg') { - // Show/hide appropriate fields - $wc('.jGraduate_' + type + '_field').show(); - $wc('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide(); - - $wc('#' + id + '_jgraduate_rect')[0] - .setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); - - // Copy stops - - curType = type === 'lg' ? 'linearGradient' : 'radialGradient'; - - $wc('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change(); - - const newGrad = $wc('#' + id + '_' + type + '_jgraduate_grad')[0]; - - if (curGradient !== newGrad) { - const curStops = $(curGradient).find('stop'); - $(newGrad).empty().append(curStops); - curGradient = newGrad; - const sm = spreadMethodOpt.val(); - curGradient.setAttribute('spreadMethod', sm); - } - showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy); - $wc('#' + id + '_jGraduate_focusCoord').toggle(showFocus); - if (showFocus) { - $wc('#' + id + '_jGraduate_match_ctr')[0].checked = false; - } - } else { - $wc(idref + ' .jGraduate_gradPick').hide(); - $wc(idref + ' .jGraduate_colPick').show(); - } - }); - $wc(idref + ' > div').hide(); - tabs.removeClass('jGraduate_tab_current'); - let tab; - switch ($this.paint.type) { - case 'linearGradient': - tab = $wc(idref + ' .jGraduate_tab_lingrad'); - break; - case 'radialGradient': - tab = $wc(idref + ' .jGraduate_tab_radgrad'); - break; - default: - tab = $wc(idref + ' .jGraduate_tab_color'); - break; - } - $this.show(); - - // jPicker will try to show after a 0ms timeout, so need to fire this after that - setTimeout(() => { - tab.addClass('jGraduate_tab_current').click(); - }, 10); }); + + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + numstops = stops.length; + // if there are not at least two stops, then + if (numstops < 2) { + while (numstops < 2) { + curGradient.append(document.createElementNS(ns.svg, 'stop')); + ++numstops; + } + stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop'); + } + + let slider; + + const setSlider = function (e) { + const {offset: {left}} = slider; + const div = slider.parent; + let x = (e.pageX - left - Number.parseInt(div.css('border-left-width'))); + if (x > SLIDERW) x = SLIDERW; + if (x <= 0) x = 0; + const posx = x - 5; + x /= SLIDERW; + + switch (slider.type) { + case 'radius': + x = (x * 2) ** 2.5; + if (x > 0.98 && x < 1.02) x = 1; + if (x <= 0.01) x = 0.01; + curGradient.setAttribute('r', x); + break; + case 'opacity': + $this.paint.alpha = Number.parseInt(x * 100); + previewRect.setAttribute('fill-opacity', x); + break; + case 'ellip': + scaleX = 1; + scaleY = 1; + if (x < 0.5) { + x /= 0.5; // 0.001 + scaleX = x <= 0 ? 0.01 : x; + } else if (x > 0.5) { + x /= 0.5; // 2 + x = 2 - x; + scaleY = x <= 0 ? 0.01 : x; + } + xform(); + x -= 1; + if (scaleY === x + 1) { + x = Math.abs(x); + } + break; + case 'angle': + x -= 0.5; + angle = x *= 180; + xform(); + x /= 100; + break; + } + slider.elem.css({'margin-left': posx}); + x = Math.round(x * 100); + slider.input.val(x); + }; + + let ellipVal = 0, angleVal = 0; + + if (curType === 'radialGradient') { + const tlist = curGradient.gradientTransform.baseVal; + if (tlist.numberOfItems === 2) { + const t = tlist.getItem(0); + const s = tlist.getItem(1); + if (t.type === 2 && s.type === 3) { + const m = s.matrix; + if (m.a !== 1) { + ellipVal = Math.round(-(1 - m.a) * 100); + } else if (m.d !== 1) { + ellipVal = Math.round((1 - m.d) * 100); + } + } + } else if (tlist.numberOfItems === 3) { + // Assume [R][T][S] + const r = tlist.getItem(0); + const t = tlist.getItem(1); + const s = tlist.getItem(2); + + if (r.type === 4 && + t.type === 2 && + s.type === 3 + ) { + angleVal = Math.round(r.angle); + const m = s.matrix; + if (m.a !== 1) { + ellipVal = Math.round(-(1 - m.a) * 100); + } else if (m.d !== 1) { + ellipVal = Math.round((1 - m.d) * 100); + } + } + } + } + + const sliders = { + radius: { + handle: '#' + id + '_jGraduate_RadiusArrows', + input: '#' + id + '_jGraduate_RadiusInput', + val: (curGradient.getAttribute('r') || 0.5) * 100 + }, + opacity: { + handle: '#' + id + '_jGraduate_OpacArrows', + input: '#' + id + '_jGraduate_OpacInput', + val: $this.paint.alpha || 100 + }, + ellip: { + handle: '#' + id + '_jGraduate_EllipArrows', + input: '#' + id + '_jGraduate_EllipInput', + val: ellipVal + }, + angle: { + handle: '#' + id + '_jGraduate_AngleArrows', + input: '#' + id + '_jGraduate_AngleInput', + val: angleVal + } + }; + + $.each(sliders, function (type, data) { + const handle = $(data.handle); + handle.mousedown(function (evt) { + const parent = handle.parent(); + slider = { + type, + elem: handle, + input: $(data.input), + parent, + offset: parent.offset() + }; + $win.mousemove(dragSlider).mouseup(stopSlider); + evt.preventDefault(); + }); + + $(data.input).val(data.val).change(function () { + const isRad = curType === 'radialGradient'; + let val = Number(this.value); + let xpos = 0; + switch (type) { + case 'radius': + if (isRad) curGradient.setAttribute('r', val / 100); + xpos = (((val / 100) ** (1 / 2.5)) / 2) * SLIDERW; + break; + + case 'opacity': + $this.paint.alpha = val; + previewRect.setAttribute('fill-opacity', val / 100); + xpos = val * (SLIDERW / 100); + break; + + case 'ellip': + scaleX = scaleY = 1; + if (val === 0) { + xpos = SLIDERW * 0.5; + break; + } + if (val > 99.5) val = 99.5; + if (val > 0) { + scaleY = 1 - (val / 100); + } else { + scaleX = -(val / 100) - 1; + } + + xpos = SLIDERW * ((val + 100) / 2) / 100; + if (isRad) xform(); + break; + + case 'angle': + angle = val; + xpos = angle / 180; + xpos += 0.5; + xpos *= SLIDERW; + if (isRad) xform(); + } + if (xpos > SLIDERW) { + xpos = SLIDERW; + } else if (xpos < 0) { + xpos = 0; + } + handle.css({'margin-left': xpos - 5}); + }).change(); + }); + + const dragSlider = function (evt) { + setSlider(evt); + evt.preventDefault(); + }; + + const stopSlider = function (evt) { + $win.unbind('mousemove', dragSlider).unbind('mouseup', stopSlider); + slider = null; + }; + + // -------------- + let thisAlpha = ($this.paint.alpha * 255 / 100).toString(16); + while (thisAlpha.length < 2) { thisAlpha = '0' + thisAlpha; } + thisAlpha = thisAlpha.split('.')[0]; + color = $this.paint.solidColor === 'none' ? '' : $this.paint.solidColor + thisAlpha; + + if (!isSolid) { + color = stops[0].getAttribute('stop-color'); + } + + // This should be done somewhere else, probably + $.extend(jPickerDefaults.window, { + alphaSupport: true, effects: {type: 'show', speed: 0} + }); + + jPickerMethod( + colPicker, + { + window: {title: $settings.window.pickerTitle}, + images: {clientPath: $settings.images.clientPath}, + color: {active: color, alphaSupport: true} + }, + function (clr) { + $this.paint.type = 'solidColor'; + $this.paint.alpha = clr.val('ahex') ? Math.round((clr.val('a') / 255) * 100) : 100; + $this.paint.solidColor = clr.val('hex') ? clr.val('hex') : 'none'; + $this.paint.radialGradient = null; + okClicked(); + }, + null, + function () { cancelClicked(); } + ); + // JFH !!!! + // const tabs = $wc(idref + ' .jGraduate_tabs li'); + const tabs = $wc('.jGraduate_tabs li'); + tabs.click(function () { + tabs.removeClass('jGraduate_tab_current'); + $(this).addClass('jGraduate_tab_current'); + $wc(idref + ' > div').hide(); + const type = $(this).attr('data-type'); + $wc(idref + ' .jGraduate_gradPick').show(); + if (type === 'rg' || type === 'lg') { + // Show/hide appropriate fields + $wc('.jGraduate_' + type + '_field').show(); + $wc('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field').hide(); + + $wc('#' + id + '_jgraduate_rect')[0] + .setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)'); + + // Copy stops + + curType = type === 'lg' ? 'linearGradient' : 'radialGradient'; + + $wc('#' + id + '_jGraduate_OpacInput').val($this.paint.alpha).change(); + + const newGrad = $wc('#' + id + '_' + type + '_jgraduate_grad')[0]; + + if (curGradient !== newGrad) { + const curStops = $(curGradient).find('stop'); + $(newGrad).empty().append(curStops); + curGradient = newGrad; + const sm = spreadMethodOpt.getAttribute('value'); + curGradient.setAttribute('spreadMethod', sm); + } + showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy); + $wc('#' + id + '_jGraduate_focusCoord').toggle(showFocus); + if (showFocus) { + $wc('#' + id + '_jGraduate_match_ctr')[0].checked = false; + } + } else { + $wc(idref + ' .jGraduate_gradPick').hide(); + $wc(idref + ' .jGraduate_colPick').show(); + } + }); + $wc(idref + ' > div').hide(); + tabs.removeClass('jGraduate_tab_current'); + let tab; + switch ($this.paint.type) { + case 'linearGradient': + tab = $wc(idref + ' .jGraduate_tab_lingrad'); + break; + case 'radialGradient': + tab = $wc(idref + ' .jGraduate_tab_radgrad'); + break; + default: + tab = $wc(idref + ' .jGraduate_tab_color'); + break; + } + $this.style.display = 'block'; + + // jPicker will try to show after a 0ms timeout, so need to fire this after that + setTimeout(() => { + tab.addClass('jGraduate_tab_current').click(); + }, 10); + // }); } // return $; diff --git a/src/editor/components/jgraduate/jQuery.jPicker.js b/src/editor/components/jgraduate/jQuery.jPicker.js index 808abc65..9c64240e 100755 --- a/src/editor/components/jgraduate/jQuery.jPicker.js +++ b/src/editor/components/jgraduate/jQuery.jPicker.js @@ -606,1037 +606,1068 @@ const {Color, List, ColorMethods} = jPicker; // local copies for YUI compressor * @returns {external:jQuery} */ export function jPickerMethod (elem, options, commitCallback, liveCallback, cancelCallback) { - return elem.each(function () { - const that = this, - settings = $.extend(true, {}, jPickerDefaults, options); // local copies for YUI compressor - if ($(that).get(0).nodeName.toLowerCase() === 'input') { // Add color picker icon if binding to an input element and bind the events to the input - $.extend(true, settings, { - window: { - bindToInput: true, - expandable: true, - input: $(that) - } - }); - if ($(that).val() === '') { - settings.color.active = new Color({hex: null}); - settings.color.current = new Color({hex: null}); - } else if (ColorMethods.validateHex($(that).val())) { - settings.color.active = new Color({hex: $(that).val(), a: settings.color.active.val('a')}); - settings.color.current = new Color({hex: $(that).val(), a: settings.color.active.val('a')}); + // return elem.each(function () { + const that = elem, + settings = $.extend(true, {}, jPickerDefaults, options); // local copies for YUI compressor + if ($(that).get(0).nodeName.toLowerCase() === 'input') { // Add color picker icon if binding to an input element and bind the events to the input + $.extend(true, settings, { + window: { + bindToInput: true, + expandable: true, + input: $(that) } + }); + if ($(that).val() === '') { + settings.color.active = new Color({hex: null}); + settings.color.current = new Color({hex: null}); + } else if (ColorMethods.validateHex($(that).val())) { + settings.color.active = new Color({hex: $(that).val(), a: settings.color.active.val('a')}); + settings.color.current = new Color({hex: $(that).val(), a: settings.color.active.val('a')}); } - if (settings.window.expandable) { - $(that).after('    '); - } else { - settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results - } - const isLessThanIE7 = Number.parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters; // needed to run the AlphaImageLoader function for IE6 - // set color mode and update visuals for the new color mode - /** - * - * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode - * @throws {Error} Invalid mode - * @returns {void} - */ - function setColorMode (colorMode) { - const {active} = color, // local copies for YUI compressor - // {clientPath} = images, - hex = active.val('hex'); - let rgbMap, rgbBar; - settings.color.mode = colorMode; - switch (colorMode) { - case 'h': - setTimeout(function () { - setBG.call(that, colorMapDiv, 'transparent'); - setImgLoc.call(that, colorMapL1, 0); - setAlpha.call(that, colorMapL1, 100); - setImgLoc.call(that, colorMapL2, 260); - setAlpha.call(that, colorMapL2, 100); - setBG.call(that, colorBarDiv, 'transparent'); - setImgLoc.call(that, colorBarL1, 0); - setAlpha.call(that, colorBarL1, 100); - setImgLoc.call(that, colorBarL2, 260); - setAlpha.call(that, colorBarL2, 100); - setImgLoc.call(that, colorBarL3, 260); - setAlpha.call(that, colorBarL3, 100); - setImgLoc.call(that, colorBarL4, 260); - setAlpha.call(that, colorBarL4, 100); - setImgLoc.call(that, colorBarL6, 260); - setAlpha.call(that, colorBarL6, 100); - }, 0); - colorMap.range('all', {minX: 0, maxX: 100, minY: 0, maxY: 100}); - colorBar.range('rangeY', {minY: 0, maxY: 360}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('s'), y: 100 - active.val('v')}, colorMap); - colorBar.val('y', 360 - active.val('h'), colorBar); - break; - case 's': - setTimeout(function () { - setBG.call(that, colorMapDiv, 'transparent'); - setImgLoc.call(that, colorMapL1, -260); - setImgLoc.call(that, colorMapL2, -520); - setImgLoc.call(that, colorBarL1, -260); - setImgLoc.call(that, colorBarL2, -520); - setImgLoc.call(that, colorBarL6, 260); - setAlpha.call(that, colorBarL6, 100); - }, 0); - colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); - colorBar.range('rangeY', {minY: 0, maxY: 100}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap); - colorBar.val('y', 100 - active.val('s'), colorBar); - break; - case 'v': - setTimeout(function () { - setBG.call(that, colorMapDiv, '000000'); - setImgLoc.call(that, colorMapL1, -780); - setImgLoc.call(that, colorMapL2, 260); - setBG.call(that, colorBarDiv, hex); - setImgLoc.call(that, colorBarL1, -520); - setImgLoc.call(that, colorBarL2, 260); - setAlpha.call(that, colorBarL2, 100); - setImgLoc.call(that, colorBarL6, 260); - setAlpha.call(that, colorBarL6, 100); - }, 0); - colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); - colorBar.range('rangeY', {minY: 0, maxY: 100}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('s')}, colorMap); - colorBar.val('y', 100 - active.val('v'), colorBar); - break; - case 'r': - rgbMap = -1040; - rgbBar = -780; - colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); - colorBar.range('rangeY', {minY: 0, maxY: 255}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('g')}, colorMap); - colorBar.val('y', 255 - active.val('r'), colorBar); - break; - case 'g': - rgbMap = -1560; - rgbBar = -1820; - colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); - colorBar.range('rangeY', {minY: 0, maxY: 255}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('r')}, colorMap); - colorBar.val('y', 255 - active.val('g'), colorBar); - break; - case 'b': - rgbMap = -2080; - rgbBar = -2860; - colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); - colorBar.range('rangeY', {minY: 0, maxY: 255}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('r'), y: 255 - active.val('g')}, colorMap); - colorBar.val('y', 255 - active.val('b'), colorBar); - break; - case 'a': - setTimeout(function () { - setBG.call(that, colorMapDiv, 'transparent'); - setImgLoc.call(that, colorMapL1, -260); - setImgLoc.call(that, colorMapL2, -520); - setImgLoc.call(that, colorBarL1, 260); - setImgLoc.call(that, colorBarL2, 260); - setAlpha.call(that, colorBarL2, 100); - setImgLoc.call(that, colorBarL6, 0); - setAlpha.call(that, colorBarL6, 100); - }, 0); - colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); - colorBar.range('rangeY', {minY: 0, maxY: 255}); - if (isNullish(active.val('ahex'))) break; - colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap); - colorBar.val('y', 255 - active.val('a'), colorBar); - break; - default: - throw new Error('Invalid Mode'); - } - switch (colorMode) { - case 'h': - break; - case 's': - case 'v': - case 'a': - setTimeout(function () { - setAlpha.call(that, colorMapL1, 100); - setAlpha.call(that, colorBarL1, 100); - setImgLoc.call(that, colorBarL3, 260); - setAlpha.call(that, colorBarL3, 100); - setImgLoc.call(that, colorBarL4, 260); - setAlpha.call(that, colorBarL4, 100); - }, 0); - break; - case 'r': - case 'g': - case 'b': - setTimeout(function () { - setBG.call(that, colorMapDiv, 'transparent'); - setBG.call(that, colorBarDiv, 'transparent'); - setAlpha.call(that, colorBarL1, 100); - setAlpha.call(that, colorMapL1, 100); - setImgLoc.call(that, colorMapL1, rgbMap); - setImgLoc.call(that, colorMapL2, rgbMap - 260); - setImgLoc.call(that, colorBarL1, rgbBar - 780); - setImgLoc.call(that, colorBarL2, rgbBar - 520); - setImgLoc.call(that, colorBarL3, rgbBar); - setImgLoc.call(that, colorBarL4, rgbBar - 260); - setImgLoc.call(that, colorBarL6, 260); - setAlpha.call(that, colorBarL6, 100); - }, 0); - break; - } - if (isNullish(active.val('ahex'))) return; - activeColorChanged.call(that, active); - } - /** - * Update color when user changes text values. - * @param {external:jQuery} ui - * @param {?module:jPicker.Slider} context - * @returns {void} - */ - function activeColorChanged (ui, context) { - if (isNullish(context) || (context !== colorBar && context !== colorMap)) positionMapAndBarArrows.call(that, ui, context); + } + if (settings.window.expandable) { + $(that).after('    '); + } else { + settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results + } + const isLessThanIE7 = Number.parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters; // needed to run the AlphaImageLoader function for IE6 + // set color mode and update visuals for the new color mode + /** + * + * @param {"h"|"s"|"v"|"r"|"g"|"b"|"a"} colorMode + * @throws {Error} Invalid mode + * @returns {void} + */ + function setColorMode (colorMode) { + const {active} = color, // local copies for YUI compressor + // {clientPath} = images, + hex = active.val('hex'); + let rgbMap, rgbBar; + settings.color.mode = colorMode; + switch (colorMode) { + case 'h': setTimeout(function () { - updatePreview.call(that, ui); - updateMapVisuals.call(that, ui); - updateBarVisuals.call(that, ui); + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, 0); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL2, 260); + setAlpha.call(that, colorMapL2, 100); + setBG.call(that, colorBarDiv, 'transparent'); + setImgLoc.call(that, colorBarL1, 0); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); }, 0); + colorMap.range('all', {minX: 0, maxX: 100, minY: 0, maxY: 100}); + colorBar.range('rangeY', {minY: 0, maxY: 360}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('s'), y: 100 - active.val('v')}, colorMap); + colorBar.val('y', 360 - active.val('h'), colorBar); + break; + case 's': + setTimeout(function () { + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, -260); + setImgLoc.call(that, colorBarL2, -520); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); + }, 0); + colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); + colorBar.range('rangeY', {minY: 0, maxY: 100}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap); + colorBar.val('y', 100 - active.val('s'), colorBar); + break; + case 'v': + setTimeout(function () { + setBG.call(that, colorMapDiv, '000000'); + setImgLoc.call(that, colorMapL1, -780); + setImgLoc.call(that, colorMapL2, 260); + setBG.call(that, colorBarDiv, hex); + setImgLoc.call(that, colorBarL1, -520); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); + }, 0); + colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); + colorBar.range('rangeY', {minY: 0, maxY: 100}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('s')}, colorMap); + colorBar.val('y', 100 - active.val('v'), colorBar); + break; + case 'r': + rgbMap = -1040; + rgbBar = -780; + colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); + colorBar.range('rangeY', {minY: 0, maxY: 255}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('g')}, colorMap); + colorBar.val('y', 255 - active.val('r'), colorBar); + break; + case 'g': + rgbMap = -1560; + rgbBar = -1820; + colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); + colorBar.range('rangeY', {minY: 0, maxY: 255}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('b'), y: 255 - active.val('r')}, colorMap); + colorBar.val('y', 255 - active.val('g'), colorBar); + break; + case 'b': + rgbMap = -2080; + rgbBar = -2860; + colorMap.range('all', {minX: 0, maxX: 255, minY: 0, maxY: 255}); + colorBar.range('rangeY', {minY: 0, maxY: 255}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('r'), y: 255 - active.val('g')}, colorMap); + colorBar.val('y', 255 - active.val('b'), colorBar); + break; + case 'a': + setTimeout(function () { + setBG.call(that, colorMapDiv, 'transparent'); + setImgLoc.call(that, colorMapL1, -260); + setImgLoc.call(that, colorMapL2, -520); + setImgLoc.call(that, colorBarL1, 260); + setImgLoc.call(that, colorBarL2, 260); + setAlpha.call(that, colorBarL2, 100); + setImgLoc.call(that, colorBarL6, 0); + setAlpha.call(that, colorBarL6, 100); + }, 0); + colorMap.range('all', {minX: 0, maxX: 360, minY: 0, maxY: 100}); + colorBar.range('rangeY', {minY: 0, maxY: 255}); + if (isNullish(active.val('ahex'))) break; + colorMap.val('xy', {x: active.val('h'), y: 100 - active.val('v')}, colorMap); + colorBar.val('y', 255 - active.val('a'), colorBar); + break; + default: + throw new Error('Invalid Mode'); } + switch (colorMode) { + case 'h': + break; + case 's': + case 'v': + case 'a': + setTimeout(function () { + setAlpha.call(that, colorMapL1, 100); + setAlpha.call(that, colorBarL1, 100); + setImgLoc.call(that, colorBarL3, 260); + setAlpha.call(that, colorBarL3, 100); + setImgLoc.call(that, colorBarL4, 260); + setAlpha.call(that, colorBarL4, 100); + }, 0); + break; + case 'r': + case 'g': + case 'b': + setTimeout(function () { + setBG.call(that, colorMapDiv, 'transparent'); + setBG.call(that, colorBarDiv, 'transparent'); + setAlpha.call(that, colorBarL1, 100); + setAlpha.call(that, colorMapL1, 100); + setImgLoc.call(that, colorMapL1, rgbMap); + setImgLoc.call(that, colorMapL2, rgbMap - 260); + setImgLoc.call(that, colorBarL1, rgbBar - 780); + setImgLoc.call(that, colorBarL2, rgbBar - 520); + setImgLoc.call(that, colorBarL3, rgbBar); + setImgLoc.call(that, colorBarL4, rgbBar - 260); + setImgLoc.call(that, colorBarL6, 260); + setAlpha.call(that, colorBarL6, 100); + }, 0); + break; + } + if (isNullish(active.val('ahex'))) return; + activeColorChanged.call(that, active); + } + /** + * Update color when user changes text values. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {void} + */ + function activeColorChanged (ui, context) { + if (isNullish(context) || (context !== colorBar && context !== colorMap)) positionMapAndBarArrows.call(that, ui, context); + setTimeout(function () { + updatePreview.call(that, ui); + updateMapVisuals.call(that, ui); + updateBarVisuals.call(that, ui); + }, 0); + } - /** - * User has dragged the ColorMap pointer. - * @param {external:jQuery} ui - * @param {?module:jPicker.Slider} context - * @returns {void} - */ - function mapValueChanged (ui, context) { - const {active} = color; - if (context !== colorMap && isNullish(active.val())) return; - const xy = ui.val('all'); - switch (settings.color.mode) { - case 'h': - active.val('sv', {s: xy.x, v: 100 - xy.y}, context); - break; - case 's': - case 'a': - active.val('hv', {h: xy.x, v: 100 - xy.y}, context); - break; - case 'v': - active.val('hs', {h: xy.x, s: 100 - xy.y}, context); - break; - case 'r': - active.val('gb', {g: 255 - xy.y, b: xy.x}, context); - break; - case 'g': - active.val('rb', {r: 255 - xy.y, b: xy.x}, context); - break; - case 'b': - active.val('rg', {r: xy.x, g: 255 - xy.y}, context); - break; - } + /** + * User has dragged the ColorMap pointer. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {void} + */ + function mapValueChanged (ui, context) { + const {active} = color; + if (context !== colorMap && isNullish(active.val())) return; + const xy = ui.val('all'); + switch (settings.color.mode) { + case 'h': + active.val('sv', {s: xy.x, v: 100 - xy.y}, context); + break; + case 's': + case 'a': + active.val('hv', {h: xy.x, v: 100 - xy.y}, context); + break; + case 'v': + active.val('hs', {h: xy.x, s: 100 - xy.y}, context); + break; + case 'r': + active.val('gb', {g: 255 - xy.y, b: xy.x}, context); + break; + case 'g': + active.val('rb', {r: 255 - xy.y, b: xy.x}, context); + break; + case 'b': + active.val('rg', {r: xy.x, g: 255 - xy.y}, context); + break; } + } - /** - * User has dragged the ColorBar slider. - * @param {external:jQuery} ui - * @param {?module:jPicker.Slider} context - * @returns {void} - */ - function colorBarValueChanged (ui, context) { - const {active} = color; - if (context !== colorBar && isNullish(active.val())) return; - switch (settings.color.mode) { - case 'h': - active.val('h', {h: 360 - ui.val('y')}, context); - break; - case 's': - active.val('s', {s: 100 - ui.val('y')}, context); - break; - case 'v': - active.val('v', {v: 100 - ui.val('y')}, context); - break; - case 'r': - active.val('r', {r: 255 - ui.val('y')}, context); - break; - case 'g': - active.val('g', {g: 255 - ui.val('y')}, context); - break; - case 'b': - active.val('b', {b: 255 - ui.val('y')}, context); - break; - case 'a': - active.val('a', 255 - ui.val('y'), context); - break; - } + /** + * User has dragged the ColorBar slider. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {void} + */ + function colorBarValueChanged (ui, context) { + const {active} = color; + if (context !== colorBar && isNullish(active.val())) return; + switch (settings.color.mode) { + case 'h': + active.val('h', {h: 360 - ui.val('y')}, context); + break; + case 's': + active.val('s', {s: 100 - ui.val('y')}, context); + break; + case 'v': + active.val('v', {v: 100 - ui.val('y')}, context); + break; + case 'r': + active.val('r', {r: 255 - ui.val('y')}, context); + break; + case 'g': + active.val('g', {g: 255 - ui.val('y')}, context); + break; + case 'b': + active.val('b', {b: 255 - ui.val('y')}, context); + break; + case 'a': + active.val('a', 255 - ui.val('y'), context); + break; } + } - /** - * Position map and bar arrows to match current color. - * @param {external:jQuery} ui - * @param {?module:jPicker.Slider} context - * @returns {void} - */ - function positionMapAndBarArrows (ui, context) { - if (context !== colorMap) { - switch (settings.color.mode) { - case 'h': { - const sv = ui.val('sv'); - colorMap.val('xy', {x: !isNullish(sv) ? sv.s : 100, y: 100 - (!isNullish(sv) ? sv.v : 100)}, context); - break; - } case 's': - // Fall through - case 'a': { - const hv = ui.val('hv'); - colorMap.val('xy', {x: (hv && hv.h) || 0, y: 100 - (!isNullish(hv) ? hv.v : 100)}, context); - break; - } case 'v': { - const hs = ui.val('hs'); - colorMap.val('xy', {x: (hs && hs.h) || 0, y: 100 - (!isNullish(hs) ? hs.s : 100)}, context); - break; - } case 'r': { - const bg = ui.val('bg'); - colorMap.val('xy', {x: (bg && bg.b) || 0, y: 255 - ((bg && bg.g) || 0)}, context); - break; - } case 'g': { - const br = ui.val('br'); - colorMap.val('xy', {x: (br && br.b) || 0, y: 255 - ((br && br.r) || 0)}, context); - break; - } case 'b': { - const rg = ui.val('rg'); - colorMap.val('xy', {x: (rg && rg.r) || 0, y: 255 - ((rg && rg.g) || 0)}, context); - break; - } - } - } - if (context !== colorBar) { - switch (settings.color.mode) { - case 'h': - colorBar.val('y', 360 - (ui.val('h') || 0), context); - break; - case 's': { - const s = ui.val('s'); - colorBar.val('y', 100 - (!isNullish(s) ? s : 100), context); - break; - } case 'v': { - const v = ui.val('v'); - colorBar.val('y', 100 - (!isNullish(v) ? v : 100), context); - break; - } case 'r': - colorBar.val('y', 255 - (ui.val('r') || 0), context); - break; - case 'g': - colorBar.val('y', 255 - (ui.val('g') || 0), context); - break; - case 'b': - colorBar.val('y', 255 - (ui.val('b') || 0), context); - break; - case 'a': { - const a = ui.val('a'); - colorBar.val('y', 255 - (!isNullish(a) ? a : 255), context); - break; - } - } - } - } - /** - * @param {external:jQuery} ui - * @returns {void} - */ - function updatePreview (ui) { - try { - const all = ui.val('all'); - activePreview.css({backgroundColor: (all && '#' + all.hex) || 'transparent'}); - setAlpha.call(that, activePreview, (all && toFixedNumeric((all.a * 100) / 255, 4)) || 0); - } catch (e) {} - } - /** - * @param {external:jQuery} ui - * @returns {void} - */ - function updateMapVisuals (ui) { + /** + * Position map and bar arrows to match current color. + * @param {external:jQuery} ui + * @param {?module:jPicker.Slider} context + * @returns {void} + */ + function positionMapAndBarArrows (ui, context) { + if (context !== colorMap) { switch (settings.color.mode) { - case 'h': - setBG.call(that, colorMapDiv, new Color({h: ui.val('h') || 0, s: 100, v: 100}).val('hex')); + case 'h': { + const sv = ui.val('sv'); + colorMap.val('xy', {x: !isNullish(sv) ? sv.s : 100, y: 100 - (!isNullish(sv) ? sv.v : 100)}, context); break; - case 's': + } case 's': + // Fall through case 'a': { + const hv = ui.val('hv'); + colorMap.val('xy', {x: (hv && hv.h) || 0, y: 100 - (!isNullish(hv) ? hv.v : 100)}, context); + break; + } case 'v': { + const hs = ui.val('hs'); + colorMap.val('xy', {x: (hs && hs.h) || 0, y: 100 - (!isNullish(hs) ? hs.s : 100)}, context); + break; + } case 'r': { + const bg = ui.val('bg'); + colorMap.val('xy', {x: (bg && bg.b) || 0, y: 255 - ((bg && bg.g) || 0)}, context); + break; + } case 'g': { + const br = ui.val('br'); + colorMap.val('xy', {x: (br && br.b) || 0, y: 255 - ((br && br.r) || 0)}, context); + break; + } case 'b': { + const rg = ui.val('rg'); + colorMap.val('xy', {x: (rg && rg.r) || 0, y: 255 - ((rg && rg.g) || 0)}, context); + break; + } + } + } + if (context !== colorBar) { + switch (settings.color.mode) { + case 'h': + colorBar.val('y', 360 - (ui.val('h') || 0), context); + break; + case 's': { const s = ui.val('s'); - setAlpha.call(that, colorMapL2, 100 - (!isNullish(s) ? s : 100)); + colorBar.val('y', 100 - (!isNullish(s) ? s : 100), context); break; } case 'v': { const v = ui.val('v'); - setAlpha.call(that, colorMapL1, !isNullish(v) ? v : 100); + colorBar.val('y', 100 - (!isNullish(v) ? v : 100), context); break; } case 'r': - setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('r') || 0) / 255 * 100, 4)); + colorBar.val('y', 255 - (ui.val('r') || 0), context); break; case 'g': - setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('g') || 0) / 255 * 100, 4)); + colorBar.val('y', 255 - (ui.val('g') || 0), context); break; case 'b': - setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('b') || 0) / 255 * 100)); + colorBar.val('y', 255 - (ui.val('b') || 0), context); + break; + case 'a': { + const a = ui.val('a'); + colorBar.val('y', 255 - (!isNullish(a) ? a : 255), context); break; } + } + } + } + /** + * @param {external:jQuery} ui + * @returns {void} + */ + function updatePreview (ui) { + try { + const all = ui.val('all'); + activePreview.css({backgroundColor: (all && '#' + all.hex) || 'transparent'}); + setAlpha.call(that, activePreview, (all && toFixedNumeric((all.a * 100) / 255, 4)) || 0); + } catch (e) {} + } + /** + * @param {external:jQuery} ui + * @returns {void} + */ + function updateMapVisuals (ui) { + switch (settings.color.mode) { + case 'h': + setBG.call(that, colorMapDiv, new Color({h: ui.val('h') || 0, s: 100, v: 100}).val('hex')); + break; + case 's': + case 'a': { + const s = ui.val('s'); + setAlpha.call(that, colorMapL2, 100 - (!isNullish(s) ? s : 100)); + break; + } case 'v': { + const v = ui.val('v'); + setAlpha.call(that, colorMapL1, !isNullish(v) ? v : 100); + break; + } case 'r': + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('r') || 0) / 255 * 100, 4)); + break; + case 'g': + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('g') || 0) / 255 * 100, 4)); + break; + case 'b': + setAlpha.call(that, colorMapL2, toFixedNumeric((ui.val('b') || 0) / 255 * 100)); + break; + } + const a = ui.val('a'); + setAlpha.call(that, colorMapL3, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4)); + } + /** + * @param {external:jQuery} ui + * @returns {void} + */ + function updateBarVisuals (ui) { + switch (settings.color.mode) { + case 'h': { const a = ui.val('a'); - setAlpha.call(that, colorMapL3, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4)); - } - /** - * @param {external:jQuery} ui - * @returns {void} - */ - function updateBarVisuals (ui) { - switch (settings.color.mode) { - case 'h': { - const a = ui.val('a'); - setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4)); - break; - } case 's': { - const hva = ui.val('hva'), - saturatedColor = new Color({h: (hva && hva.h) || 0, s: 100, v: !isNullish(hva) ? hva.v : 100}); - setBG.call(that, colorBarDiv, saturatedColor.val('hex')); - setAlpha.call(that, colorBarL2, 100 - (!isNullish(hva) ? hva.v : 100)); - setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hva && hva.a) || 0)) * 100) / 255, 4)); - break; - } case 'v': { - const hsa = ui.val('hsa'), - valueColor = new Color({h: (hsa && hsa.h) || 0, s: !isNullish(hsa) ? hsa.s : 100, v: 100}); - setBG.call(that, colorBarDiv, valueColor.val('hex')); - setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hsa && hsa.a) || 0)) * 100) / 255, 4)); - break; - } case 'r': - case 'g': - case 'b': { - const rgba = ui.val('rgba'); - let hValue = 0, vValue = 0; - if (settings.color.mode === 'r') { - hValue = (rgba && rgba.b) || 0; - vValue = (rgba && rgba.g) || 0; - } else if (settings.color.mode === 'g') { - hValue = (rgba && rgba.b) || 0; - vValue = (rgba && rgba.r) || 0; - } else if (settings.color.mode === 'b') { - hValue = (rgba && rgba.r) || 0; - vValue = (rgba && rgba.g) || 0; - } - const middle = vValue > hValue ? hValue : vValue; - setAlpha.call(that, colorBarL2, hValue > vValue ? toFixedNumeric(((hValue - vValue) / (255 - vValue)) * 100, 4) : 0); - setAlpha.call(that, colorBarL3, vValue > hValue ? toFixedNumeric(((vValue - hValue) / (255 - hValue)) * 100, 4) : 0); - setAlpha.call(that, colorBarL4, toFixedNumeric((middle / 255) * 100, 4)); - setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((rgba && rgba.a) || 0)) * 100) / 255, 4)); - break; - } case 'a': { - const a = ui.val('a'); - setBG.call(that, colorBarDiv, ui.val('hex') || '000000'); - setAlpha.call(that, colorBarL5, !isNullish(a) ? 0 : 100); - setAlpha.call(that, colorBarL6, !isNullish(a) ? 100 : 0); - break; - } + setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - (a || 0)) * 100) / 255, 4)); + break; + } case 's': { + const hva = ui.val('hva'), + saturatedColor = new Color({h: (hva && hva.h) || 0, s: 100, v: !isNullish(hva) ? hva.v : 100}); + setBG.call(that, colorBarDiv, saturatedColor.val('hex')); + setAlpha.call(that, colorBarL2, 100 - (!isNullish(hva) ? hva.v : 100)); + setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hva && hva.a) || 0)) * 100) / 255, 4)); + break; + } case 'v': { + const hsa = ui.val('hsa'), + valueColor = new Color({h: (hsa && hsa.h) || 0, s: !isNullish(hsa) ? hsa.s : 100, v: 100}); + setBG.call(that, colorBarDiv, valueColor.val('hex')); + setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((hsa && hsa.a) || 0)) * 100) / 255, 4)); + break; + } case 'r': + case 'g': + case 'b': { + const rgba = ui.val('rgba'); + let hValue = 0, vValue = 0; + if (settings.color.mode === 'r') { + hValue = (rgba && rgba.b) || 0; + vValue = (rgba && rgba.g) || 0; + } else if (settings.color.mode === 'g') { + hValue = (rgba && rgba.b) || 0; + vValue = (rgba && rgba.r) || 0; + } else if (settings.color.mode === 'b') { + hValue = (rgba && rgba.r) || 0; + vValue = (rgba && rgba.g) || 0; } + const middle = vValue > hValue ? hValue : vValue; + setAlpha.call(that, colorBarL2, hValue > vValue ? toFixedNumeric(((hValue - vValue) / (255 - vValue)) * 100, 4) : 0); + setAlpha.call(that, colorBarL3, vValue > hValue ? toFixedNumeric(((vValue - hValue) / (255 - hValue)) * 100, 4) : 0); + setAlpha.call(that, colorBarL4, toFixedNumeric((middle / 255) * 100, 4)); + setAlpha.call(that, colorBarL5, toFixedNumeric(((255 - ((rgba && rgba.a) || 0)) * 100) / 255, 4)); + break; + } case 'a': { + const a = ui.val('a'); + setBG.call(that, colorBarDiv, ui.val('hex') || '000000'); + setAlpha.call(that, colorBarL5, !isNullish(a) ? 0 : 100); + setAlpha.call(that, colorBarL6, !isNullish(a) ? 100 : 0); + break; } - /** - * @param {external:jQuery} el - * @param {string} [c="transparent"] - * @returns {void} - */ - function setBG (el, c) { - el.css({backgroundColor: (c && c.length === 6 && '#' + c) || 'transparent'}); } + } + /** + * @param {external:jQuery} el + * @param {string} [c="transparent"] + * @returns {void} + */ + function setBG (el, c) { + el.css({backgroundColor: (c && c.length === 6 && '#' + c) || 'transparent'}); + } - /** - * @param {external:jQuery} img - * @param {string} src The image source - * @returns {void} - */ - function setImg (img, src) { - if (isLessThanIE7 && (src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png'))) { - img.attr('pngSrc', src); - img.css({backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')'}); - } else img.css({backgroundImage: 'url(\'' + src + '\')'}); - } - /** - * @param {external:jQuery} img - * @param {Float} y - * @returns {void} - */ - function setImgLoc (img, y) { - img.css({top: y + 'px'}); - } - /** - * @param {external:jQuery} obj - * @param {Float} alpha - * @returns {void} - */ - function setAlpha (obj, alpha) { - obj.css({visibility: alpha > 0 ? 'visible' : 'hidden'}); - if (alpha > 0 && alpha < 100) { - if (isLessThanIE7) { - const src = obj.attr('pngSrc'); - if (!isNullish(src) && ( - src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png') - )) { - obj.css({ - filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + - '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' - }); - } else obj.css({opacity: toFixedNumeric(alpha / 100, 4)}); - } else obj.css({opacity: toFixedNumeric(alpha / 100, 4)}); - } else if (alpha === 0 || alpha === 100) { - if (isLessThanIE7) { - const src = obj.attr('pngSrc'); - if (!isNullish(src) && ( - src.includes('AlphaBar.png') || src.includes('Bars.png') || src.includes('Maps.png') - )) { - obj.css({ - filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + - '\', sizingMethod=\'scale\')' - }); - } else obj.css({opacity: ''}); - } else obj.css({opacity: ''}); - } - } - - /** - * Revert color to original color when opened. - * @returns {void} - */ - function revertColor () { - color.active.val('ahex', color.current.val('ahex')); - } - /** - * Commit the color changes. - * @returns {void} - */ - function commitColor () { - color.current.val('ahex', color.active.val('ahex')); - } - /** - * @param {Event} e - * @returns {void} - */ - function radioClicked (e) { - $(this).parents('tbody:first').find('input:radio[value!="' + e.target.value + '"]').removeAttr('checked'); - setColorMode.call(that, e.target.value); - } - /** - * - * @returns {void} - */ - function currentClicked () { - revertColor.call(that); - } - /** - * - * @returns {void} - */ - function cancelClicked () { - revertColor.call(that); - settings.window.expandable && hide.call(that); - typeof cancelCallback === 'function' && cancelCallback.call(that, color.active, cancelButton); - } - /** - * - * @returns {void} - */ - function okClicked () { - commitColor.call(that); - settings.window.expandable && hide.call(that); - typeof commitCallback === 'function' && commitCallback.call(that, color.active, okButton); - } - /** - * - * @returns {void} - */ - function iconImageClicked () { - show.call(that); - } - /** - * @param {external:jQuery} ui - * @returns {void} - */ - function currentColorChanged (ui) { - const hex = ui.val('hex'); - currentPreview.css({backgroundColor: (hex && '#' + hex) || 'transparent'}); - setAlpha.call(that, currentPreview, toFixedNumeric(((ui.val('a') || 0) * 100) / 255, 4)); - } - /** - * @param {external:jQuery} ui - * @returns {void} - */ - function expandableColorChanged (ui) { - const hex = ui.val('hex'); - const va = ui.val('va'); - iconColor.css({backgroundColor: (hex && '#' + hex) || 'transparent'}); - setAlpha.call(that, iconAlpha, toFixedNumeric(((255 - ((va && va.a) || 0)) * 100) / 255, 4)); - if (settings.window.bindToInput && settings.window.updateInputColor) { - settings.window.input.css({ - backgroundColor: (hex && '#' + hex) || 'transparent', - color: isNullish(va) || va.v > 75 ? '#000000' : '#ffffff' - }); - } - } - /** - * @param {Event} e - * @returns {void} - */ - function moveBarMouseDown (e) { - // const {element} = settings.window, // local copies for YUI compressor - // {page} = settings.window; - elementStartX = Number.parseInt(container.css('left')); - elementStartY = Number.parseInt(container.css('top')); - pageStartX = e.pageX; - pageStartY = e.pageY; - // bind events to document to move window - we will unbind these on mouseup - $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp); - e.preventDefault(); // prevent attempted dragging of the column - } - /** - * @param {Event} e - * @returns {false} - */ - function documentMouseMove (e) { - container.css({ - left: elementStartX - (pageStartX - e.pageX) + 'px', - top: elementStartY - (pageStartY - e.pageY) + 'px' - }); - if (settings.window.expandable && !$.support.boxModel) { - container.prev().css({ - left: container.css('left'), - top: container.css('top') - }); - } - e.stopPropagation(); - e.preventDefault(); - return false; - } - /** - * @param {Event} e - * @returns {false} - */ - function documentMouseUp (e) { - $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp); - e.stopPropagation(); - e.preventDefault(); - return false; - } - /** - * @param {Event} e - * @returns {false} - */ - function quickPickClicked (e) { - e.preventDefault(); - e.stopPropagation(); - color.active.val('ahex', $(this).attr('title') || null, e.target); - return false; - } - /** - * - * @returns {void} - */ - function show () { - color.current.val('ahex', color.active.val('ahex')); - /** - * - * @returns {void} - */ - function attachIFrame () { - if (!settings.window.expandable || $.support.boxModel) return; - const table = container.find('table:first'); - container.before('