Merge branch 'rgb-pickers' into work

box-drawing
Ondřej Hruška 7 years ago
commit 58eb4cfbed
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 6
      .babelrc
  2. 3
      .eslintignore
  3. 2
      js/index.js
  4. 128
      js/lib/color_utils.js
  5. 604
      js/lib/colortriangle.js
  6. 13
      js/term/themes.js
  7. 105
      js/term_conf.js
  8. 84
      pages/cfg_term.php

@ -6,13 +6,9 @@
"last 2 versions", "last 2 versions",
"> 4%", "> 4%",
"ie 11", "ie 11",
"safari 8", "safari 8"
"android 4.4"
] ]
} }
}],
["minify", {
"mergeVars": false
}] }]
] ]
} }

@ -2,7 +2,8 @@
out/**/* out/**/*
# libraries # libraries
js/lib/* js/lib/chibi.js
js/lib/polyfills.js
# php generated file # php generated file
js/lang.js js/lang.js

@ -14,3 +14,5 @@ window.$ = $
window.qs = qs window.qs = qs
window.themes = require('./term/themes') window.themes = require('./term/themes')
window.TermConf = require('./term_conf')

@ -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)
})
}
}
}
}

@ -1,4 +1,5 @@
const $ = require('../lib/chibi') const $ = require('../lib/chibi')
const { rgb255_to_hex } = require('../lib/color_utils')
const themes = exports.themes = [ const themes = exports.themes = [
[ // 0 - Tango - terminator [ // 0 - Tango - terminator
@ -73,7 +74,7 @@ exports.buildColorTable = function () {
// 256color lookup table // 256color lookup table
// should not be used to look up 0-15 (will return transparent) // should not be used to look up 0-15 (will return transparent)
colorTable256 = new Array(16).fill('rgba(0, 0, 0, 0)') colorTable256 = new Array(16).fill('#000000')
// fill color table // fill color table
// colors 16-231 are a 6x6x6 color cube // colors 16-231 are a 6x6x6 color cube
@ -83,14 +84,14 @@ exports.buildColorTable = function () {
let redValue = red * 40 + (red ? 55 : 0) let redValue = red * 40 + (red ? 55 : 0)
let greenValue = green * 40 + (green ? 55 : 0) let greenValue = green * 40 + (green ? 55 : 0)
let blueValue = blue * 40 + (blue ? 55 : 0) let blueValue = blue * 40 + (blue ? 55 : 0)
colorTable256.push(`rgb(${redValue}, ${greenValue}, ${blueValue})`) colorTable256.push(rgb255_to_hex(redValue, greenValue, blueValue))
} }
} }
} }
// colors 232-255 are a grayscale ramp, sans black and white // colors 232-255 are a grayscale ramp, sans black and white
for (let gray = 0; gray < 24; gray++) { for (let gray = 0; gray < 24; gray++) {
let value = gray * 10 + 8 let value = gray * 10 + 8
colorTable256.push(`rgb(${value}, ${value}, ${value})`) colorTable256.push(rgb255_to_hex(value, value, value))
} }
return colorTable256 return colorTable256
@ -102,17 +103,17 @@ exports.SELECTION_BG = '#b2d7fe'
exports.themePreview = function (themeN) { exports.themePreview = function (themeN) {
$('[data-fg]').forEach((elem) => { $('[data-fg]').forEach((elem) => {
let shade = elem.dataset.fg let shade = elem.dataset.fg
if (/^\d+$/.test(shade)) shade = exports.toCss(shade, themeN) if (/^\d+$/.test(shade)) shade = exports.toHex(shade, themeN)
elem.style.color = shade elem.style.color = shade
}) })
$('[data-bg]').forEach((elem) => { $('[data-bg]').forEach((elem) => {
let shade = elem.dataset.bg let shade = elem.dataset.bg
if (/^\d+$/.test(shade)) shade = exports.toCss(shade, themeN) if (/^\d+$/.test(shade)) shade = exports.toHex(shade, themeN)
elem.style.backgroundColor = shade elem.style.backgroundColor = shade
}) })
} }
exports.toCss = function (shade, themeN) { exports.toHex = function (shade, themeN) {
if (/^\d+$/.test(shade)) { if (/^\d+$/.test(shade)) {
shade = +shade shade = +shade
if (shade < 16) shade = themes[themeN][shade] if (shade < 16) shade = themes[themeN][shade]

@ -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 + '">&nbsp;' + lbl + '&nbsp;</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()
}

@ -26,8 +26,8 @@
<option value="8">Apple II</option> <option value="8">Apple II</option>
<option value="9">Commodore</option> <option value="9">Commodore</option>
</select> </select>
<span onclick="prevTheme()" class="mq-no-phone theme-nav-btn"></span> <span onclick="TermConf.prevTheme()" class="mq-no-phone theme-nav-btn"></span>
<span onclick="nextTheme()" class="mq-no-phone theme-nav-btn"></span> <span onclick="TermConf.nextTheme()" class="mq-no-phone theme-nav-btn"></span>
</div> </div>
<div class="Row color-preview"> <div class="Row color-preview">
@ -300,30 +300,6 @@
</form> </form>
<script> <script>
function showColor() {
var ex = qs('.color-example');
var fg = $('#default_fg').val();
var 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';
}
var themeN = +$('#theme').val();
ex.dataset.fg = fg;
ex.dataset.bg = bg;
themes.themePreview(themeN);
$('.colorprev.fg span').css('background', themes.toCss(bg, themeN));
}
$.ready(function () { $.ready(function () {
$('#cursor_shape').val('%cursor_shape%'); $('#cursor_shape').val('%cursor_shape%');
$('#theme').val('%theme%'); $('#theme').val('%theme%');
@ -331,58 +307,6 @@
$('#uart_parity').val('%uart_parity%'); $('#uart_parity').val('%uart_parity%');
$('#uart_stopbits').val('%uart_stopbits%'); $('#uart_stopbits').val('%uart_stopbits%');
$('#theme').on('change', showColor); TermConf.init();
});
$('#default_fg').on('input', showColor)
$('#default_bg').on('input', showColor)
$('.colorprev.bg span').on('click', function () {
var bg = this.dataset.bg;
if (typeof bg != 'undefined') $('#default_bg').val(bg);
showColor()
});
$('.colorprev.fg span').on('click', function () {
var fg = this.dataset.fg;
if (typeof fg != 'undefined') $('#default_fg').val(fg);
showColor()
});
var $presets = $('#fgbg_presets');
for (var i = 0; i < themes.fgbgThemes.length; i++) {
var thm = themes.fgbgThemes[i];
var fg = thm[0];
var bg = thm[1];
var lbl = thm[2];
var tit = thm[3];
$presets
.htmlAppend(
'<span class="preset" ' +
'data-xfg="' + fg + '" data-xbg="' + bg + '" ' +
'style="color:' + fg + ';background:' + bg + '" title="' + tit + '">&nbsp;' + lbl + '&nbsp;</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 nextTheme() {
var sel = qs('#theme');
var i = sel.selectedIndex;
sel.options[++i % sel.options.length].selected = true;
showColor();
}
function prevTheme() {
var sel = qs('#theme');
var i = sel.selectedIndex;
sel.options[(sel.options.length+(--i)) % sel.options.length].selected = true;
showColor();
}
</script> </script>

Loading…
Cancel
Save