commit
						58eb4cfbed
					
				@ -0,0 +1,128 @@ | 
				
			|||||||
 | 
					/* | 
				
			||||||
 | 
					 * Copyright (c) 2010 Tim Baumann | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions: | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software. | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
				
			||||||
 | 
					 * THE SOFTWARE. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NOTE:
 | 
				
			||||||
 | 
					// Extracted from ColorTriangle and
 | 
				
			||||||
 | 
					// Converted to ES6 by MightyPork (2017)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************* | 
				
			||||||
 | 
					 * Color conversion * | 
				
			||||||
 | 
					 *******************/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const M = Math | 
				
			||||||
 | 
					const PI = M.PI | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.hue_to_rgb = function (v1, v2, h) { | 
				
			||||||
 | 
					  if (h < 0) h += 1 | 
				
			||||||
 | 
					  if (h > 1) h -= 1 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((6 * h) < 1) return v1 + (v2 - v1) * 6 * h | 
				
			||||||
 | 
					  if ((2 * h) < 1) return v2 | 
				
			||||||
 | 
					  if ((3 * h) < 2) return v1 + (v2 - v1) * ((2 / 3) - h) * 6 | 
				
			||||||
 | 
					  return v1 | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.hsl_to_rgb = function (h, s, l) { | 
				
			||||||
 | 
					  h /= 2 * PI | 
				
			||||||
 | 
					  let r, g, b | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (s === 0) { | 
				
			||||||
 | 
					    r = g = b = l | 
				
			||||||
 | 
					  } else { | 
				
			||||||
 | 
					    let var_1, var_2 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (l < 0.5) var_2 = l * (1 + s) | 
				
			||||||
 | 
					    else var_2 = (l + s) - (s * l) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var_1 = 2 * l - var_2 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r = exports.hue_to_rgb(var_1, var_2, h + (1 / 3)) | 
				
			||||||
 | 
					    g = exports.hue_to_rgb(var_1, var_2, h) | 
				
			||||||
 | 
					    b = exports.hue_to_rgb(var_1, var_2, h - (1 / 3)) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					  return [r, g, b] | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.rgb_to_hsl = function (r, g, b) { | 
				
			||||||
 | 
					  const min = M.min(r, g, b) | 
				
			||||||
 | 
					  const max = M.max(r, g, b) | 
				
			||||||
 | 
					  const d = max - min // delta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let h, s, l | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  l = (max + min) / 2 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (d === 0) { | 
				
			||||||
 | 
					    // gray
 | 
				
			||||||
 | 
					    h = s = 0 // HSL results from 0 to 1
 | 
				
			||||||
 | 
					  } else { | 
				
			||||||
 | 
					    // chroma
 | 
				
			||||||
 | 
					    if (l < 0.5) s = d / (max + min) | 
				
			||||||
 | 
					    else s = d / (2 - max - min) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const d_r = (((max - r) / 6) + (d / 2)) / d | 
				
			||||||
 | 
					    const d_g = (((max - g) / 6) + (d / 2)) / d | 
				
			||||||
 | 
					    const d_b = (((max - b) / 6) + (d / 2)) / d // deltas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (r === max) h = d_b - d_g | 
				
			||||||
 | 
					    else if (g === max) h = (1 / 3) + d_r - d_b | 
				
			||||||
 | 
					    else if (b === max) h = (2 / 3) + d_g - d_r | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (h < 0) h += 1 | 
				
			||||||
 | 
					    else if (h > 1) h -= 1 | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					  h *= 2 * PI | 
				
			||||||
 | 
					  return [h, s, l] | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.hex_to_rgb = function (hex) { | 
				
			||||||
 | 
					  const groups = hex.match(/^#([A-Fa-f0-9]+)$/) | 
				
			||||||
 | 
					  if (groups && groups[1].length % 3 === 0) { | 
				
			||||||
 | 
					    hex = groups[1] | 
				
			||||||
 | 
					    const bytes = hex.length / 3 | 
				
			||||||
 | 
					    const max = Math.pow(16, bytes) - 1 | 
				
			||||||
 | 
					    const r = parseInt(hex.slice(0 * bytes, 1 * bytes), 16) / max | 
				
			||||||
 | 
					    const g = parseInt(hex.slice(1 * bytes, 2 * bytes), 16) / max | 
				
			||||||
 | 
					    const b = parseInt(hex.slice(2 * bytes, 3 * bytes), 16) / max | 
				
			||||||
 | 
					    return [r, g, b] | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					  return [0, 0, 0] | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function pad (n) { | 
				
			||||||
 | 
					  if (n.length === 1) n = '0' + n | 
				
			||||||
 | 
					  return n | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.rgb255_to_hex = function (r, g, b) { | 
				
			||||||
 | 
					  r = r.toString(16) | 
				
			||||||
 | 
					  g = g.toString(16) | 
				
			||||||
 | 
					  b = b.toString(16) | 
				
			||||||
 | 
					  return `#${pad(r)}${pad(g)}${pad(b)}` | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.rgb_to_hex = function (r, g, b) { | 
				
			||||||
 | 
					  r = Math.round(r * 255).toString(16) | 
				
			||||||
 | 
					  g = Math.round(g * 255).toString(16) | 
				
			||||||
 | 
					  b = Math.round(b * 255).toString(16) | 
				
			||||||
 | 
					  return `#${pad(r)}${pad(g)}${pad(b)}` | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,604 @@ | 
				
			|||||||
 | 
					/* | 
				
			||||||
 | 
					 * Copyright (c) 2010 Tim Baumann | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions: | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software. | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
				
			||||||
 | 
					 * THE SOFTWARE. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NOTE: Converted to ES6 by MightyPork (2017)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { | 
				
			||||||
 | 
					  rgb_to_hex, | 
				
			||||||
 | 
					  hex_to_rgb, | 
				
			||||||
 | 
					  hsl_to_rgb, | 
				
			||||||
 | 
					  rgb_to_hsl | 
				
			||||||
 | 
					} = require('./color_utils') | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const win = window | 
				
			||||||
 | 
					const doc = document | 
				
			||||||
 | 
					const M = Math | 
				
			||||||
 | 
					const PI = M.PI | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function times (i, fn) { | 
				
			||||||
 | 
					  for (let j = 0; j < i; j++) { | 
				
			||||||
 | 
					    fn(j) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function each (obj, fn) { | 
				
			||||||
 | 
					  if (obj.length) { | 
				
			||||||
 | 
					    times(obj.length, function (i) { | 
				
			||||||
 | 
					      fn(obj[i], i) | 
				
			||||||
 | 
					    }) | 
				
			||||||
 | 
					  } else { | 
				
			||||||
 | 
					    for (let key in obj) { | 
				
			||||||
 | 
					      if (obj.hasOwnProperty(key)) { | 
				
			||||||
 | 
					        fn(obj[key], key) | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getOffsets (el) { | 
				
			||||||
 | 
					  let left = 0 | 
				
			||||||
 | 
					  let top = 0 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (el !== null) { | 
				
			||||||
 | 
					    console.log(el) | 
				
			||||||
 | 
					    console.log(el.offsetLeft, el.offsetTop) | 
				
			||||||
 | 
					    left += el.offsetLeft | 
				
			||||||
 | 
					    top += el.offsetTop | 
				
			||||||
 | 
					    el = el.offsetParent | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return [left, top] | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = class ColorTriangle { | 
				
			||||||
 | 
					  /**************** | 
				
			||||||
 | 
					   * ColorTriangle * | 
				
			||||||
 | 
					   ****************/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Constructor function:
 | 
				
			||||||
 | 
					  constructor (color, options) { | 
				
			||||||
 | 
					    this.options = { | 
				
			||||||
 | 
					      size: 150, | 
				
			||||||
 | 
					      padding: 8, | 
				
			||||||
 | 
					      triangleSize: 0.8, | 
				
			||||||
 | 
					      wheelPointerColor1: '#444', | 
				
			||||||
 | 
					      wheelPointerColor2: '#eee', | 
				
			||||||
 | 
					      trianglePointerSize: 16, | 
				
			||||||
 | 
					      // wheelPointerSize: 16,
 | 
				
			||||||
 | 
					      trianglePointerColor1: '#eee', | 
				
			||||||
 | 
					      trianglePointerColor2: '#444', | 
				
			||||||
 | 
					      background: 'transparent' | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this._setOptions(options) | 
				
			||||||
 | 
					    this._calculateProperties() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this._createContainer() | 
				
			||||||
 | 
					    this._createTriangle() | 
				
			||||||
 | 
					    this._createWheel() | 
				
			||||||
 | 
					    this._createWheelPointer() | 
				
			||||||
 | 
					    this._createTrianglePointer() | 
				
			||||||
 | 
					    this._attachEvents() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    color = color || '#f00' | 
				
			||||||
 | 
					    if (typeof color == 'string') { | 
				
			||||||
 | 
					      this.setHEX(color) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _calculateProperties () { | 
				
			||||||
 | 
					    let opts = this.options | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.padding = opts.padding | 
				
			||||||
 | 
					    this.innerSize = opts.size - opts.padding * 2 | 
				
			||||||
 | 
					    this.triangleSize = opts.triangleSize * this.innerSize | 
				
			||||||
 | 
					    this.wheelThickness = (this.innerSize - this.triangleSize) / 2 | 
				
			||||||
 | 
					    this.wheelPointerSize = opts.wheelPointerSize || this.wheelThickness | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.wheelRadius = (this.innerSize) / 2 | 
				
			||||||
 | 
					    this.triangleRadius = (this.triangleSize) / 2 | 
				
			||||||
 | 
					    this.triangleSideLength = M.sqrt(3) * this.triangleRadius | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _calculatePositions () { | 
				
			||||||
 | 
					    const r = this.triangleRadius | 
				
			||||||
 | 
					    const hue = this.hue | 
				
			||||||
 | 
					    const third = (2 / 3) * PI | 
				
			||||||
 | 
					    const s = this.saturation | 
				
			||||||
 | 
					    const l = this.lightness | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Colored point
 | 
				
			||||||
 | 
					    const hx = this.hx = M.cos(hue) * r | 
				
			||||||
 | 
					    const hy = this.hy = -M.sin(hue) * r | 
				
			||||||
 | 
					    // Black point
 | 
				
			||||||
 | 
					    const sx = this.sx = M.cos(hue - third) * r | 
				
			||||||
 | 
					    const sy = this.sy = -M.sin(hue - third) * r | 
				
			||||||
 | 
					    // White point
 | 
				
			||||||
 | 
					    const vx = this.vx = M.cos(hue + third) * r | 
				
			||||||
 | 
					    const vy = this.vy = -M.sin(hue + third) * r | 
				
			||||||
 | 
					    // Current point
 | 
				
			||||||
 | 
					    const mx = (sx + vx) / 2 | 
				
			||||||
 | 
					    const my = (sy + vy) / 2 | 
				
			||||||
 | 
					    const a = (1 - 2 * M.abs(l - 0.5)) * s | 
				
			||||||
 | 
					    this.x = sx + (vx - sx) * l + (hx - mx) * a | 
				
			||||||
 | 
					    this.y = sy + (vy - sy) * l + (hy - my) * a | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _createContainer () { | 
				
			||||||
 | 
					    let c = this.container = doc.createElement('div') | 
				
			||||||
 | 
					    c.className = 'color-triangle' | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c.style.display = 'block' | 
				
			||||||
 | 
					    c.style.padding = `${this.padding}px` | 
				
			||||||
 | 
					    c.style.position = 'relative' | 
				
			||||||
 | 
					    c.style.boxShadow = '0 1px 10px black' | 
				
			||||||
 | 
					    c.style.borderRadius = '5px' | 
				
			||||||
 | 
					    c.style.width = c.style.height = `${this.innerSize + 2 * this.padding}px` | 
				
			||||||
 | 
					    c.style.background = this.options.background | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _createWheel () { | 
				
			||||||
 | 
					    let c = this.wheel = doc.createElement('canvas') | 
				
			||||||
 | 
					    c.width = c.height = this.innerSize | 
				
			||||||
 | 
					    c.style.position = 'absolute' | 
				
			||||||
 | 
					    c.style.margin = c.style.padding = '0' | 
				
			||||||
 | 
					    c.style.left = c.style.top = `${this.padding}px` | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this._drawWheel(c.getContext('2d')) | 
				
			||||||
 | 
					    this.container.appendChild(c) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _drawWheel (ctx) { | 
				
			||||||
 | 
					    let s, i | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.save() | 
				
			||||||
 | 
					    ctx.translate(this.wheelRadius, this.wheelRadius) | 
				
			||||||
 | 
					    s = this.wheelRadius - this.triangleRadius | 
				
			||||||
 | 
					    // Draw a circle for every color
 | 
				
			||||||
 | 
					    for (i = 0; i < 360; i++) { | 
				
			||||||
 | 
					      ctx.rotate(PI / -180) // rotate one degree
 | 
				
			||||||
 | 
					      ctx.beginPath() | 
				
			||||||
 | 
					      ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)' | 
				
			||||||
 | 
					      ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, PI * 2, true) | 
				
			||||||
 | 
					      ctx.fill() | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    ctx.restore() | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _createTriangle () { | 
				
			||||||
 | 
					    let c = this.triangle = doc.createElement('canvas') | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c.width = c.height = this.innerSize | 
				
			||||||
 | 
					    c.style.position = 'absolute' | 
				
			||||||
 | 
					    c.style.margin = c.style.padding = '0' | 
				
			||||||
 | 
					    c.style.left = c.style.top = this.padding + 'px' | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.triangleCtx = c.getContext('2d') | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.container.appendChild(c) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _drawTriangle () { | 
				
			||||||
 | 
					    const hx = this.hx | 
				
			||||||
 | 
					    const hy = this.hy | 
				
			||||||
 | 
					    const sx = this.sx | 
				
			||||||
 | 
					    const sy = this.sy | 
				
			||||||
 | 
					    const vx = this.vx | 
				
			||||||
 | 
					    const vy = this.vy | 
				
			||||||
 | 
					    const size = this.innerSize | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let ctx = this.triangleCtx | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // clear
 | 
				
			||||||
 | 
					    ctx.clearRect(0, 0, size, size) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.save() | 
				
			||||||
 | 
					    ctx.translate(this.wheelRadius, this.wheelRadius) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // make a triangle
 | 
				
			||||||
 | 
					    ctx.beginPath() | 
				
			||||||
 | 
					    ctx.moveTo(hx, hy) | 
				
			||||||
 | 
					    ctx.lineTo(sx, sy) | 
				
			||||||
 | 
					    ctx.lineTo(vx, vy) | 
				
			||||||
 | 
					    ctx.closePath() | 
				
			||||||
 | 
					    ctx.clip() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.fillStyle = '#000' | 
				
			||||||
 | 
					    ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size) | 
				
			||||||
 | 
					    // => black triangle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // create gradient from hsl(hue, 1, 1) to transparent
 | 
				
			||||||
 | 
					    let grad0 = ctx.createLinearGradient(hx, hy, (sx + vx) / 2, (sy + vy) / 2) | 
				
			||||||
 | 
					    const hsla = 'hsla(' + M.round(this.hue * (180 / PI)) + ', 100%, 50%, ' | 
				
			||||||
 | 
					    grad0.addColorStop(0, hsla + '1)') | 
				
			||||||
 | 
					    grad0.addColorStop(1, hsla + '0)') | 
				
			||||||
 | 
					    ctx.fillStyle = grad0 | 
				
			||||||
 | 
					    ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size) | 
				
			||||||
 | 
					    // => gradient: one side of the triangle is black, the opponent angle is $color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // create color gradient from white to transparent
 | 
				
			||||||
 | 
					    let grad1 = ctx.createLinearGradient(vx, vy, (hx + sx) / 2, (hy + sy) / 2) | 
				
			||||||
 | 
					    grad1.addColorStop(0, '#fff') | 
				
			||||||
 | 
					    grad1.addColorStop(1, 'rgba(255, 255, 255, 0)') | 
				
			||||||
 | 
					    ctx.globalCompositeOperation = 'lighter' | 
				
			||||||
 | 
					    ctx.fillStyle = grad1 | 
				
			||||||
 | 
					    ctx.fillRect(-this.wheelRadius, -this.wheelRadius, size, size) | 
				
			||||||
 | 
					    // => white angle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.restore() | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The two pointers
 | 
				
			||||||
 | 
					  _createWheelPointer () { | 
				
			||||||
 | 
					    let c = this.wheelPointer = doc.createElement('canvas') | 
				
			||||||
 | 
					    const size = this.wheelPointerSize | 
				
			||||||
 | 
					    c.width = c.height = size | 
				
			||||||
 | 
					    c.style.position = 'absolute' | 
				
			||||||
 | 
					    c.style.margin = c.style.padding = '0' | 
				
			||||||
 | 
					    this._drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2) | 
				
			||||||
 | 
					    this.container.appendChild(c) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _moveWheelPointer () { | 
				
			||||||
 | 
					    const r = this.wheelPointerSize / 2 | 
				
			||||||
 | 
					    const s = this.wheelPointer.style | 
				
			||||||
 | 
					    s.top = this.padding + this.wheelRadius - M.sin(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px' | 
				
			||||||
 | 
					    s.left = this.padding + this.wheelRadius + M.cos(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px' | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _createTrianglePointer () { // create pointer in the triangle
 | 
				
			||||||
 | 
					    let c = this.trianglePointer = doc.createElement('canvas') | 
				
			||||||
 | 
					    const size = this.options.trianglePointerSize | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c.width = c.height = size | 
				
			||||||
 | 
					    c.style.position = 'absolute' | 
				
			||||||
 | 
					    c.style.margin = c.style.padding = '0' | 
				
			||||||
 | 
					    this._drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2) | 
				
			||||||
 | 
					    this.container.appendChild(c) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _moveTrianglePointer (x, y) { | 
				
			||||||
 | 
					    const s = this.trianglePointer.style | 
				
			||||||
 | 
					    const r = this.options.trianglePointerSize / 2 | 
				
			||||||
 | 
					    s.top = (this.y + this.wheelRadius + this.padding - r) + 'px' | 
				
			||||||
 | 
					    s.left = (this.x + this.wheelRadius + this.padding - r) + 'px' | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _drawPointer (ctx, r, color1, color2) { | 
				
			||||||
 | 
					    ctx.fillStyle = color2 | 
				
			||||||
 | 
					    ctx.beginPath() | 
				
			||||||
 | 
					    ctx.arc(r, r, r, 0, PI * 2, true) | 
				
			||||||
 | 
					    ctx.fill() // => black circle
 | 
				
			||||||
 | 
					    ctx.fillStyle = color1 | 
				
			||||||
 | 
					    ctx.beginPath() | 
				
			||||||
 | 
					    ctx.arc(r, r, r - 2, 0, PI * 2, true) | 
				
			||||||
 | 
					    ctx.fill() // => white circle with 1px black border
 | 
				
			||||||
 | 
					    ctx.fillStyle = color2 | 
				
			||||||
 | 
					    ctx.beginPath() | 
				
			||||||
 | 
					    ctx.arc(r, r, r / 4 + 2, 0, PI * 2, true) | 
				
			||||||
 | 
					    ctx.fill() // => black circle with big white border and a small black border
 | 
				
			||||||
 | 
					    ctx.globalCompositeOperation = 'destination-out' | 
				
			||||||
 | 
					    ctx.beginPath() | 
				
			||||||
 | 
					    ctx.arc(r, r, r / 4, 0, PI * 2, true) | 
				
			||||||
 | 
					    ctx.fill() // => transparent center
 | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The Element and the DOM
 | 
				
			||||||
 | 
					  inject (parent) { | 
				
			||||||
 | 
					    parent.appendChild(this.container) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // calculate canvas position on page
 | 
				
			||||||
 | 
					    const offsets = getOffsets(this.triangle) | 
				
			||||||
 | 
					    this.offset = { | 
				
			||||||
 | 
					      x: offsets[0], | 
				
			||||||
 | 
					      y: offsets[1] | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dispose () { | 
				
			||||||
 | 
					    let parent = this.container.parentNode | 
				
			||||||
 | 
					    if (parent) { | 
				
			||||||
 | 
					      parent.removeChild(this.container) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getElement () { | 
				
			||||||
 | 
					    return this.container | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Color accessors
 | 
				
			||||||
 | 
					  getCSS () { | 
				
			||||||
 | 
					    const h = Math.round(this.hue * (180 / PI)) | 
				
			||||||
 | 
					    const s = Math.round(this.saturation * 100) | 
				
			||||||
 | 
					    const l = Math.round(this.lightness * 100) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return `hsl(${h}, ${s}%, ${l}%)` | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getHEX () { | 
				
			||||||
 | 
					    return rgb_to_hex(...this.getRGB()) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setHEX (hex) { | 
				
			||||||
 | 
					    this.setRGB(...hex_to_rgb(hex)) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getRGB () { | 
				
			||||||
 | 
					    return hsl_to_rgb(...this.getHSL()) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setRGB (r, g, b) { | 
				
			||||||
 | 
					    this.setHSL(...rgb_to_hsl(r, g, b)) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getHSL () { | 
				
			||||||
 | 
					    return [this.hue, this.saturation, this.lightness] | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setHSL (h, s, l) { | 
				
			||||||
 | 
					    this.hue = h | 
				
			||||||
 | 
					    this.saturation = s | 
				
			||||||
 | 
					    this.lightness = l | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this._initColor() | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _initColor () { | 
				
			||||||
 | 
					    this._calculatePositions() | 
				
			||||||
 | 
					    this._moveWheelPointer() | 
				
			||||||
 | 
					    this._drawTriangle() | 
				
			||||||
 | 
					    this._moveTrianglePointer() | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Mouse event handling
 | 
				
			||||||
 | 
					  _attachEvents () { | 
				
			||||||
 | 
					    this.down = null | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mousedown = (evt) => { | 
				
			||||||
 | 
					      evt.stopPropagation() | 
				
			||||||
 | 
					      evt.preventDefault() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      doc.body.addEventListener('mousemove', mousemove, false) | 
				
			||||||
 | 
					      doc.body.addEventListener('mouseup', mouseup, false) | 
				
			||||||
 | 
					      this._map(evt.pageX, evt.pageY) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mousemove = (evt) => { | 
				
			||||||
 | 
					      this._move(evt.pageX, evt.pageY) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mouseup = (evt) => { | 
				
			||||||
 | 
					      if (this.down) { | 
				
			||||||
 | 
					        this.down = null | 
				
			||||||
 | 
					        this._fireEvent('dragend') | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					      doc.body.removeEventListener('mousemove', mousemove, false) | 
				
			||||||
 | 
					      doc.body.removeEventListener('mouseup', mouseup, false) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.container.addEventListener('mousedown', mousedown, false) | 
				
			||||||
 | 
					    this.container.addEventListener('mousemove', mousemove, false) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _map (x, y) { | 
				
			||||||
 | 
					    const ox = x | 
				
			||||||
 | 
					    const oy = y | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x -= this.offset.x + this.wheelRadius | 
				
			||||||
 | 
					    y -= this.offset.y + this.wheelRadius | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const r = M.sqrt(x * x + y * y) // Pythagoras
 | 
				
			||||||
 | 
					    if (r > this.triangleRadius && r < this.wheelRadius) { | 
				
			||||||
 | 
					      // Wheel
 | 
				
			||||||
 | 
					      this.down = 'wheel' | 
				
			||||||
 | 
					      this._fireEvent('dragstart') | 
				
			||||||
 | 
					      this._move(ox, oy) | 
				
			||||||
 | 
					    } else if (r < this.triangleRadius) { | 
				
			||||||
 | 
					      // Inner circle
 | 
				
			||||||
 | 
					      this.down = 'triangle' | 
				
			||||||
 | 
					      this._fireEvent('dragstart') | 
				
			||||||
 | 
					      this._move(ox, oy) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _move (x, y) { | 
				
			||||||
 | 
					    if (!this.down) { | 
				
			||||||
 | 
					      return | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x -= this.offset.x + this.wheelRadius | 
				
			||||||
 | 
					    y -= this.offset.y + this.wheelRadius | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let rad = M.atan2(-y, x) | 
				
			||||||
 | 
					    if (rad < 0) { | 
				
			||||||
 | 
					      rad += 2 * PI | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (this.down === 'wheel') { | 
				
			||||||
 | 
					      this.hue = rad | 
				
			||||||
 | 
					      this._initColor() | 
				
			||||||
 | 
					      this._fireEvent('drag') | 
				
			||||||
 | 
					    } else if (this.down === 'triangle') { | 
				
			||||||
 | 
					      // get radius and max radius
 | 
				
			||||||
 | 
					      let rad0 = (rad + 2 * PI - this.hue) % (2 * PI) | 
				
			||||||
 | 
					      let rad1 = rad0 % ((2 / 3) * PI) - (PI / 3) | 
				
			||||||
 | 
					      let a = 0.5 * this.triangleRadius | 
				
			||||||
 | 
					      let b = M.tan(rad1) * a | 
				
			||||||
 | 
					      let r = M.sqrt(x * x + y * y) // Pythagoras
 | 
				
			||||||
 | 
					      let maxR = M.sqrt(a * a + b * b) // Pythagoras
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (r > maxR) { | 
				
			||||||
 | 
					        const dx = M.tan(rad1) * r | 
				
			||||||
 | 
					        let rad2 = M.atan(dx / maxR) | 
				
			||||||
 | 
					        if (rad2 > PI / 3) { | 
				
			||||||
 | 
					          rad2 = PI / 3 | 
				
			||||||
 | 
					        } else if (rad2 < -PI / 3) { | 
				
			||||||
 | 
					          rad2 = -PI / 3 | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        rad += rad2 - rad1 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rad0 = (rad + 2 * PI - this.hue) % (2 * PI) | 
				
			||||||
 | 
					        rad1 = rad0 % ((2 / 3) * PI) - (PI / 3) | 
				
			||||||
 | 
					        b = M.tan(rad1) * a | 
				
			||||||
 | 
					        r = maxR = M.sqrt(a * a + b * b) // Pythagoras
 | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      x = M.round(M.cos(rad) * r) | 
				
			||||||
 | 
					      y = M.round(-M.sin(rad) * r) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const l = this.lightness = ((M.sin(rad0) * r) / this.triangleSideLength) + 0.5 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const widthShare = 1 - (M.abs(l - 0.5) * 2) | 
				
			||||||
 | 
					      let s = this.saturation = (((M.cos(rad0) * r) + (this.triangleRadius / 2)) / (1.5 * this.triangleRadius)) / widthShare | 
				
			||||||
 | 
					      s = M.max(0, s) // cannot be lower than 0
 | 
				
			||||||
 | 
					      s = M.min(1, s) // cannot be greater than 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.lightness = l | 
				
			||||||
 | 
					      this.saturation = s | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.x = x | 
				
			||||||
 | 
					      this.y = y | 
				
			||||||
 | 
					      this._moveTrianglePointer() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this._fireEvent('drag') | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*************** | 
				
			||||||
 | 
					   * Init helpers * | 
				
			||||||
 | 
					   ***************/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static initInput (input, options) { | 
				
			||||||
 | 
					    options = options || {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let ct | 
				
			||||||
 | 
					    let openColorTriangle = function () { | 
				
			||||||
 | 
					      let hex = input.value | 
				
			||||||
 | 
					      if (options.parseColor) hex = options.parseColor(hex) | 
				
			||||||
 | 
					      if (!ct) { | 
				
			||||||
 | 
					        options.size = options.size || input.offsetWidth | 
				
			||||||
 | 
					        options.background = win.getComputedStyle(input, null).backgroundColor | 
				
			||||||
 | 
					        options.margin = options.margin || 10 | 
				
			||||||
 | 
					        options.event = options.event || 'dragend' | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ct = new ColorTriangle(hex, options) | 
				
			||||||
 | 
					        ct.addEventListener(options.event, () => { | 
				
			||||||
 | 
					          const hex = ct.getHEX() | 
				
			||||||
 | 
					          input.value = options.uppercase ? hex.toUpperCase() : hex | 
				
			||||||
 | 
					          fireChangeEvent() | 
				
			||||||
 | 
					        }) | 
				
			||||||
 | 
					      } else { | 
				
			||||||
 | 
					        ct.setHEX(hex) | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let top = input.offsetTop | 
				
			||||||
 | 
					      if (win.innerHeight - input.getBoundingClientRect().top > input.offsetHeight + options.margin + options.size) { | 
				
			||||||
 | 
					        top += input.offsetHeight + options.margin // below
 | 
				
			||||||
 | 
					      } else { | 
				
			||||||
 | 
					        top -= options.margin + options.size // above
 | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let el = ct.getElement() | 
				
			||||||
 | 
					      el.style.position = 'absolute' | 
				
			||||||
 | 
					      el.style.left = input.offsetLeft + 'px' | 
				
			||||||
 | 
					      el.style.top = top + 'px' | 
				
			||||||
 | 
					      el.style.zIndex = '1338' // above everything
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ct.inject(input.parentNode) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let closeColorTriangle = () => { | 
				
			||||||
 | 
					      if (ct) { | 
				
			||||||
 | 
					        ct.dispose() | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let fireChangeEvent = () => { | 
				
			||||||
 | 
					      let evt = doc.createEvent('HTMLEvents') | 
				
			||||||
 | 
					      evt.initEvent('input', true, false) // bubbles = true, cancable = false
 | 
				
			||||||
 | 
					      input.dispatchEvent(evt) // fire event
 | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    input.addEventListener('focus', openColorTriangle, false) | 
				
			||||||
 | 
					    input.addEventListener('blur', closeColorTriangle, false) | 
				
			||||||
 | 
					    input.addEventListener('keyup', () => { | 
				
			||||||
 | 
					      const val = input.value | 
				
			||||||
 | 
					      if (val.match(/^#((?:[0-9A-Fa-f]{3})|(?:[0-9A-Fa-f]{6}))$/)) { | 
				
			||||||
 | 
					        openColorTriangle() | 
				
			||||||
 | 
					        fireChangeEvent() | 
				
			||||||
 | 
					      } else { | 
				
			||||||
 | 
					        closeColorTriangle() | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    }, false) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /******************* | 
				
			||||||
 | 
					   * Helper functions * | 
				
			||||||
 | 
					   *******************/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _setOptions (opts) { | 
				
			||||||
 | 
					    opts = opts || {} | 
				
			||||||
 | 
					    let dflt = this.options | 
				
			||||||
 | 
					    let options = this.options = {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    each(dflt, function (val, key) { | 
				
			||||||
 | 
					      options[key] = (opts.hasOwnProperty(key)) | 
				
			||||||
 | 
					        ? opts[key] | 
				
			||||||
 | 
					        : val | 
				
			||||||
 | 
					    }) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  addEventListener (type, fn) { | 
				
			||||||
 | 
					    if (!this.events) { | 
				
			||||||
 | 
					      this.events = {} | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    if (!this.events[type]) { | 
				
			||||||
 | 
					      this.events[type] = [] | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    this.events[type].push(fn) | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  removeEventListener (type, fn) { | 
				
			||||||
 | 
					    if (this.events) { | 
				
			||||||
 | 
					      let fns = this.events[type] | 
				
			||||||
 | 
					      const l = fns.length | 
				
			||||||
 | 
					      for (let i = 0; i < l; i += 1) { | 
				
			||||||
 | 
					        if (fns[i] === fn) { | 
				
			||||||
 | 
					          fns.splice(i, 1) | 
				
			||||||
 | 
					          break | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _fireEvent (type) { | 
				
			||||||
 | 
					    if (this.events) { | 
				
			||||||
 | 
					      let evts = this.events[type] | 
				
			||||||
 | 
					      if (evts) { | 
				
			||||||
 | 
					        const args = Array.prototype.slice.call(arguments, 1) | 
				
			||||||
 | 
					        each(evts, function (evt) { | 
				
			||||||
 | 
					          evt(...args) | 
				
			||||||
 | 
					        }) | 
				
			||||||
 | 
					      } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,105 @@ | 
				
			|||||||
 | 
					const ColorTriangle = require('./lib/colortriangle') | 
				
			||||||
 | 
					const $ = require('./lib/chibi') | 
				
			||||||
 | 
					const themes = require('./term/themes') | 
				
			||||||
 | 
					const { qs } = require('./utils') | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function selectedTheme () { | 
				
			||||||
 | 
					  return +$('#theme').val() | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.init = function () { | 
				
			||||||
 | 
					  $('#theme').on('change', showColor) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $('#default_fg').on('input', showColor) | 
				
			||||||
 | 
					  $('#default_bg').on('input', showColor) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let opts = { | 
				
			||||||
 | 
					    padding: 10, | 
				
			||||||
 | 
					    event: 'drag', | 
				
			||||||
 | 
					    uppercase: true, | 
				
			||||||
 | 
					    trianglePointerSize: 20, | 
				
			||||||
 | 
					    // wheelPointerSize: 12,
 | 
				
			||||||
 | 
					    size: 200, | 
				
			||||||
 | 
					    parseColor: (color) => { | 
				
			||||||
 | 
					      return themes.toHex(color, selectedTheme()) | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ColorTriangle.initInput(qs('#default_fg'), opts) | 
				
			||||||
 | 
					  ColorTriangle.initInput(qs('#default_bg'), opts) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $('.colorprev.bg span').on('click', function () { | 
				
			||||||
 | 
					    const bg = this.dataset.bg | 
				
			||||||
 | 
					    if (typeof bg != 'undefined') $('#default_bg').val(bg) | 
				
			||||||
 | 
					    showColor() | 
				
			||||||
 | 
					  }) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $('.colorprev.fg span').on('click', function () { | 
				
			||||||
 | 
					    const fg = this.dataset.fg | 
				
			||||||
 | 
					    if (typeof fg != 'undefined') $('#default_fg').val(fg) | 
				
			||||||
 | 
					    showColor() | 
				
			||||||
 | 
					  }) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let $presets = $('#fgbg_presets') | 
				
			||||||
 | 
					  for (let i = 0; i < themes.fgbgThemes.length; i++) { | 
				
			||||||
 | 
					    const thm = themes.fgbgThemes[i] | 
				
			||||||
 | 
					    const fg = thm[0] | 
				
			||||||
 | 
					    const bg = thm[1] | 
				
			||||||
 | 
					    const lbl = thm[2] | 
				
			||||||
 | 
					    const tit = thm[3] | 
				
			||||||
 | 
					    $presets.htmlAppend( | 
				
			||||||
 | 
					        '<span class="preset" ' + | 
				
			||||||
 | 
					        'data-xfg="' + fg + '" data-xbg="' + bg + '" ' + | 
				
			||||||
 | 
					        'style="color:' + fg + ';background:' + bg + '" title="' + tit + '"> ' + lbl + ' </span>') | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((i + 1) % 5 === 0) $presets.htmlAppend('<br>') | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $('.preset').on('click', function () { | 
				
			||||||
 | 
					    $('#default_fg').val(this.dataset.xfg) | 
				
			||||||
 | 
					    $('#default_bg').val(this.dataset.xbg) | 
				
			||||||
 | 
					    showColor() | 
				
			||||||
 | 
					  }) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  showColor() | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function showColor () { | 
				
			||||||
 | 
					  let ex = qs('.color-example') | 
				
			||||||
 | 
					  let fg = $('#default_fg').val() | 
				
			||||||
 | 
					  let bg = $('#default_bg').val() | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (/^\d+$/.test(fg)) { | 
				
			||||||
 | 
					    fg = +fg | 
				
			||||||
 | 
					  } else if (!/^#[\da-f]{6}$/i.test(fg)) { | 
				
			||||||
 | 
					    fg = 'black' | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (/^\d+$/.test(bg)) { | 
				
			||||||
 | 
					    bg = +bg | 
				
			||||||
 | 
					  } else if (!/^#[\da-f]{6}$/i.test(bg)) { | 
				
			||||||
 | 
					    bg = 'black' | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const themeN = selectedTheme() | 
				
			||||||
 | 
					  ex.dataset.fg = fg | 
				
			||||||
 | 
					  ex.dataset.bg = bg | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  themes.themePreview(themeN) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $('.colorprev.fg span').css('background', themes.toHex(bg, themeN)) | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.nextTheme = () => { | 
				
			||||||
 | 
					  let sel = qs('#theme') | 
				
			||||||
 | 
					  let i = sel.selectedIndex | 
				
			||||||
 | 
					  sel.options[++i % sel.options.length].selected = true | 
				
			||||||
 | 
					  showColor() | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.prevTheme = () => { | 
				
			||||||
 | 
					  let sel = qs('#theme') | 
				
			||||||
 | 
					  let i = sel.selectedIndex | 
				
			||||||
 | 
					  sel.options[(sel.options.length + (--i)) % sel.options.length].selected = true | 
				
			||||||
 | 
					  showColor() | 
				
			||||||
 | 
					} | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue