/** * Silex, live web creation * http://projects.silexlabs.org/?/silex/ * * Copyright (c) 2012 Silex Labs * http://www.silexlabs.org/ * * Silex is available under the GPL license * http://www.silexlabs.org/silex/silex-licensing/ */ /** * @fileoverview This class is a color picker component used in the properties. * It let the user choose a color with an opacity, i.e. color is css * rgba(r,g,b,a) or no color at all, i.e. value is `transparent` It uses the * browser'scolor picker for the color */ import {Style} from '../utils/style'; export class ColorPicker { // store for later use element: HTMLElement; cbk: () => void; color = ''; isDisabled = true; isIndeterminate = true; // init button which shows/hides the palete colorInput: HTMLInputElement; // alpha opacityInput: HTMLInputElement; // transparency transparentCheckbox: HTMLInputElement; /** * @param element the container of the component, it is supposed to have this * structure: * .color-edit-container * input.color-edit-text-input(type='number', min='0', max='100') * input.color-edit-color-input(type='color') * input.color-edit-transparent-check(type='checkbox', * indeterminate='true') */ constructor(element: HTMLElement, cbk: () => void) { this.element = element; this.cbk = cbk; this.colorInput = this.element.querySelector('.color-button'); this.colorInput.onchange = (e) => this.onChange(e); this.colorInput.oninput = (e) => this.onChange(e); this.opacityInput = this.element.querySelector('.color-opacity-input'); this.opacityInput.onchange = (e) => this.onChange(e); this.opacityInput.oninput = (e) => this.onChange(e); this.transparentCheckbox = this.element.querySelector('.color-edit-transparent-check'); this.transparentCheckbox.onchange = (e) => this.onChange(e); } setDisabled(isDisabled: boolean) { this.isDisabled = isDisabled; this.redraw(); } setIndeterminate(isIndeterminate: boolean) { this.isIndeterminate = isIndeterminate; this.redraw(); } /** * store the new color * @param color the css color as an rgba string, i.e. rgba(r,g,b,a), * or "transparent" */ setColor(color: string) { this.color = color; this.redraw(); } getColor(): string { return this.color; } onChange(e: Event) { // let redraw update the value e.preventDefault(); e.stopPropagation(); if (!this.transparentCheckbox.checked) { const opacityPercent = parseInt(this.opacityInput.value, 10); const opacity = isNaN(opacityPercent) ? 1 : opacityPercent / 100; const hex = Math.round(opacity * 255).toString(16); this.color = Style.hexToRgba(this.colorInput.value + (hex.length === 2 ? '' : '0') + hex); } else { this.color = 'transparent'; } // notify the owner this.cbk(); // update the disabled states of the inputs // this.redraw(); } redraw() { if (this.isIndeterminate) { this.transparentCheckbox.indeterminate = true; this.opacityInput.value = ''; } else { this.transparentCheckbox.indeterminate = false; if (this.color === 'transparent' || this.color == null || this.color === '') { this.transparentCheckbox.checked = true; this.colorInput.disabled = true; this.colorInput.style.opacity = '.3'; this.opacityInput.disabled = true; this.opacityInput.value = ''; } else { this.transparentCheckbox.checked = false; this.colorInput.disabled = false; this.colorInput.style.opacity = '1'; // this will not accept rgba, only rgb: const hex = Style.rgbaToHex(this.color); this.colorInput.value = hex.substring(0, hex.length - 2); this.opacityInput.disabled = false; try { const arr = Style.rgbaToArray(this.color); this.opacityInput.value = (Math.round(arr[3] * 100 / 255)).toString(); } catch (e) { // probably not an rgba color console.warn('error, this color is probably not an rgba color', this.color, e); this.opacityInput.value = '100'; } } } if (this.isDisabled) { this.transparentCheckbox.disabled = true; this.colorInput.disabled = true; this.colorInput.style.opacity = '.3'; this.opacityInput.disabled = true; } else { this.transparentCheckbox.disabled = false; } } }