UNPKG

svgedit

Version:

Powerful SVG-Editor for your browser

1,326 lines (1,199 loc) 51.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: components/jgraduate/jQuery.jGraduate.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: components/jgraduate/jQuery.jGraduate.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* globals svgEditor */ /** * @file jGraduate 0.4 * * jQuery Plugin for a gradient picker * * @module jGraduate * @copyright 2010 Jeff Schiller {@link http://blog.codedread.com/}, 2010 Alexis Deveria {@link http://a.deveria.com/} * * @license Apache-2.0 * @example * // The Paint object is described below. * $.jGraduate.Paint(); // constructs a 'none' color * @example $.jGraduate.Paint({copy: o}); // creates a copy of the paint o * @example $.jGraduate.Paint({hex: '#rrggbb'}); // creates a solid color paint with hex = "#rrggbb" * @example $.jGraduate.Paint({linearGradient: o, a: 50}); // creates a linear gradient paint with opacity=0.5 * @example $.jGraduate.Paint({radialGradient: o, a: 7}); // creates a radial gradient paint with opacity=0.07 * @example $.jGraduate.Paint({hex: '#rrggbb', linearGradient: o}); // throws an exception? */ import SvgCanvas from '@svgedit/svgcanvas' import { jPickerDefaults, jPickerMethod } from './jQuery.jPicker.js' import { findPos } from '@svgedit/svgcanvas/common/util.js' /** * @todo JFH: This jQuery plugin was adapted to work within a Web Component. * We have to rewrite it as a pure webcomponent. */ /** * The jQuery namespace. * @external jQuery */ /** * The jQuery plugin namespace. * @namespace {PlainObject} fn * @memberof external:jQuery * @see {@link http://learn.jquery.com/plugins/|jQuery Plugins} */ const ns = { svg: 'http://www.w3.org/2000/svg', xlink: 'http://www.w3.org/1999/xlink' } if (!window.console) { window.console = { log () { /* empty fn */ }, dir () { /* empty fn */ } } } /** * Adds {@link external:jQuery.jGraduate.Paint}, * {@link external:jQuery.fn.jGraduateDefaults}, * {@link external:jQuery.fn.jGraduate}. * @function module:jGraduate.jGraduate * @param {external:jQuery} $ The jQuery instance to wrap * @returns {external:jQuery} */ // export default function jQueryPluginJGraduate ($) { /** * @namespace {PlainObject} jGraduate * @memberof external:jQuery */ export const jGraduate = /** @lends external:jQuery.jGraduate */ { /** * @class external:jQuery.jGraduate.Paint * @see module:jGraduate~Paint */ Paint: SvgCanvas.Paint } // JSDoc doesn't show this as belonging to our `module:jGraduate.Options` type, // so we use `@see` /** * @namespace {module:jGraduate.Options} jGraduateDefaults * @memberof external:jQuery.fn */ export const jGraduateDefaults = /** @lends external:jQuery.fn.jGraduateDefaults */ { /** * Creates an object with a 'none' color. * @type {external:jQuery.jGraduate.Paint} * @see module:jGraduate.Options */ paint: new jGraduate.Paint(), /** * @namespace */ window: { /** * @type {string} * @see module:jGraduate.Options */ pickerTitle: 'Drag markers to pick a paint' }, /** * @namespace */ images: { /** * @type {string} * @see module:jGraduate.Options */ clientPath: 'images/' }, /** * @type {string} * @see module:jGraduate.Options */ newstop: 'inverse' // same, inverse, black, white } const isGecko = navigator.userAgent.includes('Gecko/') /** * @typedef {PlainObject&lt;string, string>} module:jGraduate.Attrs */ /** * @param {SVGElement} elem * @param {module:jGraduate.Attrs} attrs * @returns {void} */ function setAttrs (elem, attrs) { if (isGecko) { Object.entries(attrs).forEach(([aname, val]) => { elem.setAttribute(aname, val) }) } else { Object.entries(attrs).forEach(([aname, val]) => { const prop = elem[aname] if (prop?.constructor === 'SVGLength') { prop.baseVal.value = val } else { elem.setAttribute(aname, val) } }) } } /** * @param {string} name * @param {module:jGraduate.Attrs} attrs * @param {Element} newparent * @returns {SVGElement} */ function mkElem (name, attrs, newparent) { const elem = document.createElementNS(ns.svg, name) setAttrs(elem, attrs) if (newparent) { newparent.append(elem) } return elem } /** * @typedef {PlainObject} module:jGraduate.ColorOpac Object may have one or both values * @property {string} [color] #Hex color * @property {Float} [opac] 0-1 */ /** * @typedef {PlainObject} module:jGraduate.Options * @property {module:jGraduate~Paint} [paint] A Paint object object describing the paint to display initially; defaults to a new instance without options (defaults to opaque white) * @property {external:Window} [window] * @property {string} [window.pickerTitle="Drag markers to pick a paint"] * @property {PlainObject} [images] * @property {string} [images.clientPath="images/"] * @property {"same"|"inverse"|"black"|"white"|module:jGraduate.ColorOpac} [newstop="inverse"] */ /** * @callback external:jQuery.fn.jGraduate.OkCallback * @param {external:jQuery.jGraduate.Paint} paint * @returns {void} */ /** * @callback external:jQuery.fn.jGraduate.CancelCallback * @returns {void} */ /** * @function external:jQuery.fn.jGraduate * @param {module:jGraduate.Options} [options] * @param {external:jQuery.fn.jGraduate.OkCallback} [okCallback] Called with a Paint object when Ok is pressed * @param {external:jQuery.fn.jGraduate.CancelCallback} [cancelCallback] Called with no arguments when Cancel is pressed * @returns {external:jQuery} */ export function jGraduateMethod (elem, options, okCallback, cancelCallback, i18next) { const $this = elem const $settings = Object.assign({}, jGraduateDefaults, options || {}) const id = $this.getAttribute('id') const idref = '#' + $this.getAttribute('id') + ' ' if (!idref) { 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' &amp;&amp; $this.okCallback($this.paint) $this.style.display = 'none' } const cancelClicked = function () { typeof $this.cancelCallback === 'function' &amp;&amp; $this.cancelCallback() $this.style.display = 'none' } Object.assign($this, { // 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' }) } $this.classList.add('jGraduate_Picker') $this.innerHTML = `&lt;ul class="jGraduate_tabs"> &lt;li class="jGraduate_tab_color jGraduate_tab_current" id="jGraduate_tab_color" data-type="col">${i18next.t('config.jgraduate_solid_color')}&lt;/li> &lt;li class="jGraduate_tab_lingrad" id="jGraduate_tab_lingrad" data-type="lg">${i18next.t('config.jgraduate_linear_gradient')}&lt;/li> &lt;li class="jGraduate_tab_radgrad" id="jGraduate_tab_radgrad" data-type="rg">${i18next.t('config.jgraduate_radial_gradient')}&lt;/li> &lt;/ul> &lt;div class="jGraduate_colPick" id="jGraduate_colPick">&lt;/div> &lt;div class="jGraduate_gradPick" id="jGraduate_gradPick">&lt;/div> &lt;div class="jGraduate_LightBox" id="jGraduate_LightBox">&lt;/div> &lt;div id="${id}_jGraduate_stopPicker" class="jGraduate_stopPicker">&lt;/div>` const colPicker = $this.querySelector('#jGraduate_colPick') const gradPicker = $this.querySelector('#jGraduate_gradPick') const html = `&lt;div id="${id}_jGraduate_Swatch" class="jGraduate_Swatch"> &lt;h2 class="jGraduate_Title">${$settings.window.pickerTitle}&lt;/h2> &lt;div id="${id}_jGraduate_GradContainer" class="jGraduate_GradContainer">&lt;/div> &lt;div id="${id}_jGraduate_StopSlider" class="jGraduate_StopSlider">&lt;/div> &lt;/div> &lt;div class="jGraduate_Form jGraduate_Points jGraduate_lg_field"> &lt;div class="jGraduate_StopSection"> &lt;label class="jGraduate_Form_Heading">${i18next.t('config.jgraduate_begin_point')}&lt;/label> &lt;div class="jGraduate_Form_Section"> &lt;label>x:&lt;/label> &lt;input type="text" id="${id}_jGraduate_x1" size="3" title="${i18next.t('config.jgraduate_enter_starting_x')}"/> &lt;label>y:&lt;/label> &lt;input type="text" id="${id}_jGraduate_y1" size="3" title="${i18next.t('config.jgraduate_enter_starting_y')}"/> &lt;/div> &lt;/div> &lt;div class="jGraduate_StopSection"> &lt;label class="jGraduate_Form_Heading">${i18next.t('config.jgraduate_end_point')}&lt;/label> &lt;div class="jGraduate_Form_Section"> &lt;label>x:&lt;/label> &lt;input type="text" id="${id}_jGraduate_x2" size="3" title="${i18next.t('config.jgraduate_enter_ending_x')}"/> &lt;label>y:&lt;/label> &lt;input type="text" id="${id}_jGraduate_y2" size="3" title="${i18next.t('config.jgraduate_enter_ending_y')}"/> &lt;/div> &lt;/div> &lt;/div> &lt;div class="jGraduate_Form jGraduate_Points jGraduate_rg_field"> &lt;div class="jGraduate_StopSection"> &lt;label class="jGraduate_Form_Heading">${i18next.t('config.jgraduate_center_point')}&lt;/label> &lt;div class="jGraduate_Form_Section"> &lt;label>x:&lt;/label> &lt;input type="text" id="${id}_jGraduate_cx" size="3" title="${i18next.t('config.jgraduate_enter_value_x')}"/> &lt;label>y:&lt;/label> &lt;input type="text" id="${id}_jGraduate_cy" size="3" title="${i18next.t('config.jgraduate_enter_value_y')}"/> &lt;/div> &lt;/div> &lt;div class="jGraduate_StopSection"> &lt;label class="jGraduate_Form_Heading">${i18next.t('config.jgraduate_focal_point')}&lt;/label> &lt;div class="jGraduate_Form_Section"> &lt;label>${i18next.t('config.jgraduate_match_center')} &lt;input type="checkbox" checked="checked" id="${id}_jGraduate_match_ctr"/>&lt;/label>&lt;br/> &lt;label>x:&lt;/label> &lt;input type="text" id="${id}_jGraduate_fx" size="3" title="${i18next.t('config.jgraduate_enter_focal_x')}"/> &lt;label>y:&lt;/label> &lt;input type="text" id="${id}_jGraduate_fy" size="3" title="${i18next.t('config.jgraduate_enter_focal_y')}"/> &lt;/div> &lt;/div> &lt;/div> &lt;div class="jGraduate_StopSection jGraduate_SpreadMethod"> &lt;label class="jGraduate_Form_Heading">${i18next.t('config.jgraduate_spread_method')}&lt;/label> &lt;div class="jGraduate_Form_Section"> &lt;select class="jGraduate_spreadMethod" id="jGraduate_spreadMethod"> &lt;option value=pad selected>${i18next.t('properties.jgraduate_pad')}&lt;/option> &lt;option value=reflect>${i18next.t('properties.jgraduate_reflect')}&lt;/option> &lt;option value=repeat>${i18next.t('properties.jgraduate_repeat')}&lt;/option> &lt;/select> &lt;/div> &lt;/div> &lt;div class="jGraduate_Form"> &lt;div class="jGraduate_Slider jGraduate_RadiusField jGraduate_rg_field"> &lt;label class="prelabel">${i18next.t('config.jgraduate_radius')}&lt;/label> &lt;div id="${id}_jGraduate_Radius" class="jGraduate_SliderBar jGraduate_Radius" title="${i18next.t('config.jgraduate_set_radius')}"> &lt;img id="${id}_jGraduate_RadiusArrows" class="jGraduate_RadiusArrows" src="${$settings.images.clientPath}rangearrows2.gif"> &lt;/div> &lt;label>&lt;input type="text" id="${id}_jGraduate_RadiusInput" size="3" value="100"/>%&lt;/label> &lt;/div> &lt;div class="jGraduate_Slider jGraduate_EllipField jGraduate_rg_field"> &lt;label class="prelabel">${i18next.t('config.jgraduate_ellip')}&lt;/label> &lt;div id="${id}_jGraduate_Ellip" class="jGraduate_SliderBar jGraduate_Ellip" title="${i18next.t('config.jgraduate_set_ellip')}"> &lt;img id="${id}_jGraduate_EllipArrows" class="jGraduate_EllipArrows" src="${$settings.images.clientPath}rangearrows2.gif"> &lt;/div> &lt;label>&lt;input type="text" id="${id}_jGraduate_EllipInput" size="3" value="0"/>%&lt;/label> &lt;/div> &lt;div class="jGraduate_Slider jGraduate_AngleField jGraduate_rg_field"> &lt;label class="prelabel">${i18next.t('config.jgraduate_angle')}&lt;/label> &lt;div id="${id}_jGraduate_Angle" class="jGraduate_SliderBar jGraduate_Angle" title="${i18next.t('config.jgraduate_set_angle')}"> &lt;img id="${id}_jGraduate_AngleArrows" class="jGraduate_AngleArrows" src="${$settings.images.clientPath}rangearrows2.gif"> &lt;/div> &lt;label>&lt;input type="text" id="${id}_jGraduate_AngleInput" size="3" value="0"/>${i18next.t('config.jgraduate_deg')}&lt;/label> &lt;/div> &lt;div class="jGraduate_Slider jGraduate_OpacField"> &lt;label class="prelabel">${i18next.t('config.jgraduate_opac')}&lt;/label> &lt;div id="${id}_jGraduate_Opac" class="jGraduate_SliderBar jGraduate_Opac" title="${i18next.t('config.jgraduate_set_opac')}"> &lt;img id="${id}_jGraduate_OpacArrows" class="jGraduate_OpacArrows" src="${$settings.images.clientPath}rangearrows2.gif"> &lt;/div> &lt;label>&lt;input type="text" id="${id}_jGraduate_OpacInput" size="3" value="100"/>%&lt;/label> &lt;/div> &lt;/div> &lt;div class="jGraduate_OkCancel"> &lt;input type="button" id="${id}_jGraduate_Ok" class="jGraduate_Ok" value="${i18next.t('common.ok')}"/> &lt;input type="button" id="${id}_jGraduate_Cancel" class="jGraduate_Cancel" value="${i18next.t('common.cancel')}"/> &lt;/div>` const div = document.createElement('div') div.innerHTML = html while (div.children.length > 0) { gradPicker.appendChild(div.children[0]) } /* eslint-enable max-len */ // -------------- // Set up all the SVG elements (the gradient, stops and rectangle) const MAX = 256 const MARGINX = 0 const MARGINY = 0 // STOP_RADIUS = 15 / 2, const SIZEX = MAX - 2 * MARGINX const SIZEY = MAX - 2 * MARGINY const attrInput = {} const SLIDERW = 145 const JQSliderBars = $this.querySelectorAll('.jGraduate_SliderBar') for (const JQSliderBar of JQSliderBars) { JQSliderBar.style.width = SLIDERW + 'px' } // JFH !!!!!! const container = $this.querySelector('#' + id + '_jGraduate_GradContainer') 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; // if we are sent a gradient, import it let curType = $this.paint.type let grad = $this.paint[curType] let curGradient = grad const gradalpha = $this.paint.alpha 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) } let stopGroup // eslint-disable-line prefer-const if (isSolid) { // JFH !!!!!!!! grad = curGradient = $this.querySelector('#' + id + '_lg_jgraduate_grad') 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 &lt; 6; i += 2) { // const ch = color.substr(i, 2); let inv = (255 - Number.parseInt(color.substr(i, 2), 16)).toString(16) if (inv.length &lt; 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) const y1 = Number.parseFloat(grad.getAttribute('y1') || 0.0) const x2 = Number.parseFloat(grad.getAttribute('x2') || 1.0) const y2 = Number.parseFloat(grad.getAttribute('y2') || 0.0) const cx = Number.parseFloat(grad.getAttribute('cx') || 0.5) const cy = Number.parseFloat(grad.getAttribute('cy') || 0.5) const fx = Number.parseFloat(grad.getAttribute('fx') || cx) const 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 }, svg) // stop visuals created here const beginCoord = document.createElement('div') beginCoord.setAttribute('class', 'grad_coord jGraduate_lg_field') beginCoord.setAttribute('title', 'Begin Stop') beginCoord.textContent = 1 beginCoord.style.top = y1 * MAX beginCoord.style.left = x1 * MAX beginCoord.dataset.coord = 'start' container.appendChild(beginCoord) const endCoord = document.createElement('div') endCoord.setAttribute('class', 'grad_coord jGraduate_lg_field') endCoord.setAttribute('title', 'End stop') endCoord.textContent = 2 endCoord.style.top = y2 * MAX endCoord.style.left = x2 * MAX endCoord.dataset.coord = 'end' container.appendChild(endCoord) const centerCoord = document.createElement('div') centerCoord.setAttribute('class', 'grad_coord jGraduate_rg_field') centerCoord.setAttribute('title', 'Center stop') centerCoord.textContent = 'C' centerCoord.style.top = cy * MAX centerCoord.style.left = cx * MAX centerCoord.dataset.coord = 'center' container.appendChild(centerCoord) const focusCoord = document.createElement('div') focusCoord.setAttribute('class', 'grad_coord jGraduate_rg_field') focusCoord.setAttribute('title', 'Focus point') focusCoord.textContent = 'F' focusCoord.style.top = fy * MAX focusCoord.style.left = fx * MAX focusCoord.style.display = 'none' focusCoord.dataset.coord = 'focus' focusCoord.setAttribute('id', id + '_jGraduate_focusCoord') container.appendChild(focusCoord) let showFocus const onAttrChangeHandler = (e, attr, isRadial) => { // TODO: Support values &lt; 0 and > 1 (zoomable preview?) if (isNaN(Number.parseFloat(e.target.value)) || e.target.value &lt; 0) { e.target.value = 0.0 } else if (e.target.value > 1) { e.target.value = 1.0 } if (!(attr[0] === 'f' &amp;&amp; !showFocus) &amp;&amp; ((isRadial &amp;&amp; curType === 'radialGradient') || (!isRadial &amp;&amp; curType === 'linearGradient'))) { curGradient.setAttribute(attr, e.target.value) } const $elem = isRadial ? attr[0] === 'c' ? centerCoord : focusCoord : attr[1] === '1' ? beginCoord : endCoord if (attr.includes('x') === 'left') { $elem.style.left = e.target.value * MAX } else if (attr.includes('x') === 'top') { $elem.style.top = e.target.value * MAX } } for (const [, attr] of ['x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'fx', 'fy'].entries()) { 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' } } attrInput[attr] = $this.querySelector('#' + id + '_jGraduate_' + attr) attrInput[attr].value = attrval attrInput[attr].addEventListener('change', (evt) => onAttrChangeHandler(evt, attr, isRadial)) attrInput[attr].dispatchEvent(new Event('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', { id: 'jq_stop_' + Math.floor((Math.random() * 10000) + 1), '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 { curGradient.appendChild(stop) } 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', { id: 'jq_pathbg_' + Math.floor((Math.random() * 10000) + 1), 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.addEventListener('mousedown', function (e) { selectStop(this) drag = curStop $win.addEventListener('mousemove', dragColor) $win.addEventListener('mouseup', remDrags) stopOffset = findPos(stopMakerDiv) e.preventDefault() return false }) path.dataset.stop = stop.getAttribute('id') path.dataset.bg = pathbg.getAttribute('id') path.addEventListener('dblclick', function () { $this.querySelector('#jGraduate_LightBox').style.display = 'block' 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 &lt; 2) { thisAlpha = '0' + thisAlpha } colr = stopColor.substr(1) + thisAlpha const jqPickerElem = $this.querySelector('#' + id + '_jGraduate_stopPicker') jqPickerElem.style.left = '100px' jqPickerElem.style.bottom = '15px' jPickerMethod(jqPickerElem, { window: { title: 'Pick the start color and opacity for the gradient' }, images: { clientPath: $settings.images.clientPath }, color: { active: colr, alphaSupport: true } }, function (clr) { 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) $this.querySelector('#jGraduate_LightBox').style.display = 'none' $this.querySelector('#' + id + '_jGraduate_stopPicker').style.display = 'none' }, null, function () { $this.querySelector('#jGraduate_LightBox').style.display = 'none' $this.querySelector('#' + id + '_jGraduate_stopPicker').style.display = 'none' }, i18next ) }) const jqStopEls = curGradient.querySelectorAll('stop') for (const jqStopEl of jqStopEls) { const curS = jqStopEl if (Number(jqStopEl.getAttribute('offset')) > n) { if (!colr) { const newcolor = jqStopEl.getAttribute('stop-color') const newopac = jqStopEl.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.insertAdjacentElement('beforebegin', stop) // curS.before(stop); // return false; } // return true; } if (sel) selectStop(path) return stop } /** * * @returns {void} */ function remStop () { delStop.setAttribute('display', 'none') const path = curStop delete path.dataset.stop delete path.dataset.bg curStop.parentNode.removeChild(curStop) } const stopMakerDiv = $this.querySelector('#' + id + '_jGraduate_StopSlider') let stops; let curStop; let 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.removeEventListener('mousemove', dragColor) if (delStop.getAttribute('display') !== 'none') { remStop() } drag = null } let scaleX = 1; let scaleY = 1; let angle = 0 let cX = cx let cY = cy /** * * @returns {void} */ function xform () { const rot = angle ? 'rotate(' + angle + ',' + cX + ',' + cY + ') ' : '' if (scaleX === 1 &amp;&amp; scaleY === 1) { curGradient.removeAttribute('gradientTransform') } else { const x = -cX * (scaleX - 1) const y = -cY * (scaleY - 1) curGradient.setAttribute( 'gradientTransform', rot + 'translate(' + x + ',' + y + ') scale(' + scaleX + ',' + scaleY + ')' ) } } /** * @param {Event} evt * @returns {void} */ function dragColor (evt) { let x = evt.pageX - stopOffset.left const y = evt.pageY - stopOffset.top x = x &lt; 10 ? 10 : x > MAX + 10 ? MAX + 10 : x const xfStr = 'translate(' + x + ', 26)' if (y &lt; -60 || y > 130) { delStop.setAttribute('display', 'block') delStop.setAttribute('transform', xfStr) } else { delStop.setAttribute('display', 'none') } drag.setAttribute('transform', xfStr) const jqpgpath = $this.querySelector('#' + drag.dataset.bg) jqpgpath.setAttribute('transform', xfStr) const stop = $this.querySelector('#' + drag.dataset.stop) const sX = (x - 10) / MAX stop.setAttribute('offset', sX) let last = 0 const jqStopElems = curGradient.querySelectorAll('stop'); [].forEach.call(jqStopElems, function (jqStopElem) { const cur = jqStopElem.getAttribute('offset') const t = jqStopElem if (cur &lt; last) { t.previousElementSibling.insertAdjacentElement('beforebegin', t) stops = curGradient.querySelectorAll('stop') } last = cur }) } const stopMakerSVG = mkElem('svg', { width: '100%', height: 45 }, stopMakerDiv) 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.setAttribute('href', bgImage) svgEditor.$click(stopMakerSVG, function (evt) { stopOffset = findPos(stopMakerDiv) const { target } = evt if (target.tagName === 'path') return let x = evt.pageX - stopOffset.left - 8 x = x &lt; 10 ? 10 : x > MAX + 10 ? MAX + 10 : x mkStop(x / MAX, 0, 0, true) evt.stopPropagation() }) stopMakerSVG.addEventListener('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 &lt; 0 ? 0 : x > MAX ? MAX : x y = y &lt; 0 ? 0 : y > MAX ? MAX : y draggingCoord.style.left = x + 'px' draggingCoord.style.top = y + 'px' // calculate stop offset const fracx = x / SIZEX const fracy = y / SIZEY const type = draggingCoord.dataset.coord const grd = curGradient switch (type) { case 'start': attrInput.x1.value = fracx attrInput.y1.value = fracy grd.setAttribute('x1', fracx) grd.setAttribute('y1', fracy) break case 'end': attrInput.x2.value = fracx attrInput.y2.value = fracy grd.setAttribute('x2', fracx) grd.setAttribute('y2', fracy) break case 'center': attrInput.cx.value = fracx attrInput.cy.value = fracy grd.setAttribute('cx', fracx) grd.setAttribute('cy', fracy) cX = fracx cY = fracy xform() break case 'focus': attrInput.fx.value = fracx attrInput.fy.value = fracy grd.setAttribute('fx', fracx) grd.setAttribute('fy', fracy) xform() } evt.preventDefault() } const onCoordUp = function () { draggingCoord = null $win.removeEventListener('mousemove', onCoordDrag) $win.removeEventListener('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 &lt; 2) { while (numstops &lt; 2) { curGradient.append(document.createElementNS(ns.svg, 'stop')) ++numstops } stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop') } for (let i = 0; i &lt; numstops; i++) { mkStop(0, 0, 0, 0, stops[i]) } spreadMethodOpt.setAttribute('value', curGradient.getAttribute('spreadMethod') || 'pad') let offset // No match, so show focus point showFocus = false previewRect.setAttribute('fill-opacity', gradalpha / 100) const JQGradCoords = $this.querySelectorAll('#' + id + ' div.grad_coord') const onMouseDownGradCoords = (e) => { e.preventDefault() draggingCoord = e.target offset = findPos(draggingCoord.parentNode) $win.addEventListener('mousemove', onCoordDrag) $win.addEventListener('mouseup', onCoordUp) } for (const JQGradCoord of JQGradCoords) { JQGradCoord.addEventListener('mousedown', onMouseDownGradCoords) } // bind GUI elements svgEditor.$click($this.querySelector('#' + id + '_jGraduate_Ok'), function () { $this.paint.type = curType $this.paint[curType] = curGradient.cloneNode(true) $this.paint.solidColor = null okClicked() }) svgEditor.$click($this.querySelector('#' + id + '_jGraduate_Cancel'), cancelClicked) if (curType === 'radialGradient') { if (showFocus) { focusCoord.style.display = 'block' } else { focusCoord.style.display = 'none' attrInput.fx.value = '' attrInput.fy.value = '' } } $this.querySelector('#' + id + '_jGraduate_match_ctr').checked = !showFocus let lastfx; let lastfy const onMatchCtrHandler = (e) => { showFocus = !e.target.checked if (showFocus) { focusCoord.style.display = 'block' } else { focusCoord.style.display = 'none' } attrInput.fx.value = '' attrInput.fy.value = '' 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.value = fX attrInput.fy.value = fY } } $this.querySelector('#' + id + '_jGraduate_match_ctr').addEventListener('change', onMatchCtrHandler) stops = curGradient.getElementsByTagNameNS(ns.svg, 'stop') numstops = stops.length // if there are not at least two stops, then if (numstops &lt; 2) { while (numstops &lt; 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 divi = slider.parent let x = (e.pageX - left - Number.parseInt(getComputedStyle(divi, null).getPropertyValue('border-left-width'))) if (x > SLIDERW) x = SLIDERW if (x &lt;= 0) x = 0 const posx = x - 5 x /= SLIDERW switch (slider.type) { case 'radius': x = (x * 2) ** 2.5 if (x > 0.98 &amp;&amp; x &lt; 1.02) x = 1 if (x &lt;= 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 &lt; 0.5) { x /= 0.5 // 0.001 scaleX = x &lt;= 0 ? 0.01 : x } else if (x > 0.5) { x /= 0.5 // 2 x = 2 - x scaleY = x &lt;= 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.style.marginLeft = posx + 'px' x = Math.round(x * 100) slider.input.value = x } let ellipVal = 0; let 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 &amp;&amp; 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 &amp;&amp; t.type === 2 &amp;&amp; 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 } } for (const [, [type, data]] of Object.entries(Object.entries(sliders))) { const handle = $this.querySelector(data.handle) const sInput = $this.querySelector(data.input) handle.addEventListener('mousedown', function (evt) { const parent = handle.parentNode slider = { type, elem: handle, input: sInput, parent, offset: findPos(parent) } $win.addEventListener('mousemove', dragSlider) $win.addEventListener('mouseup', stopSlider) evt.preventDefault() }) sInput.value = data.val sInput.addEventListener('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 &lt; 0) { xpos = 0 } handle.style.marginLeft = (xpos - 5) + 'px' }) sInput.dispatchEvent(new Event('change')) } const dragSlider = function (evt) { setSlider(evt) evt.preventDefault() } const stopSlider = function () { $win.removeEventListener('mousemove', dragSlider) $win.removeEventListener('mouseup', stopSlider) slider = null } // -------------- let thisAlpha = ($this.paint.alpha * 255 / 100).toString(16) while (thisAlpha.length &lt; 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 Object.assign(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() }, i18next ) // JFH !!!! const tabs = $this.querySelectorAll('.jGraduate_tabs li') const onTabsClickHandler = (e) => { for (const tab of tabs) { tab.classList.remove('jGraduate_tab_current') } e.target.classList.add('jGraduate_tab_current') const innerDivs = $this.querySelectorAll(idref + ' > div'); [].forEach.call(innerDivs, function (innerDiv) { innerDiv.style.display = 'none' }) const type = e.target.dataset.type gradPicker.style.display = 'block' if (type === 'rg' || type === 'lg') { const tFileds = $this.querySelectorAll('.jGraduate_' + type + '_field'); [].forEach.call(tFileds, function (tFiled) { tFiled.style.display = 'block' }) const t1Fileds = $this.querySelectorAll('.jGraduate_' + (type === 'lg' ? 'rg' : 'lg') + '_field'); [].forEach.call(t1Fileds, function (tFiled) { tFiled.style.display = 'none' }) $this.querySelectorAll('#' + id + '_jgraduate_rect')[0] .setAttribute('fill', 'url(#' + id + '_' + type + '_jgraduate_grad)') curType = type === 'lg' ? 'linearGradient' : 'radialGradient' const jOpacInput = $this.querySelector('#' + id + '_jGraduate_OpacInput') jOpacInput.value = $this.paint.alpha jOpacInput.dispatchEvent(new Event('change')) const newGrad = $this.querySelectorAll('#' + id + '_' + type + '_jgraduate_grad')[0] if (curGradient !== newGrad) { const curStops = curGradient.querySelectorAll('stop') while (newGrad.firstChild) { newGrad.removeChild(newGrad.firstChild) } [].forEach.call(curStops, function (curS) { newGrad.appendChild(curS) }) curGradient = newGrad const sm = spreadMethodOpt.getAttribute('value') curGradient.setAttribute('spreadMethod', sm) } showFocus = type === 'rg' &amp;&amp; curGradient.getAttribute('fx') !== null &amp;&amp; !(cx === fx &amp;&amp; cy === fy) const jQfocusCoord = $this.querySelectorAll('#' + id + '_jGraduate_focusCoord') if (jQfocusCoord[0].style.display === 'none') { jQfocusCoord[0].style.display = 'block' } else { jQfocusCoord[0].style.display = 'none' } if (showFocus) { $this.querySelectorAll('#' + id + '_jGraduate_match_ctr')[0].checked = false } } else { gradPicker.style.display = 'none' colPicker.style.display = 'block' } } for (const tab of tabs) { svgEditor.$click(tab, onTabsClickHandler) } const innerDivs = $this.querySelectorAll(idref + ' > div'); [].forEach.call(innerDivs, function (innerDiv) { innerDiv.style.display = 'none' }) for (const tab of tabs) { tab.classList.remove('jGraduate_tab_current') } let tab switch ($this.paint.type) { case 'linearGradient': tab = $this.querySelector(idref + ' .jGraduate_tab_lingrad') break case 'radialGradient': tab = $this.querySelector(idref + ' .jGraduate_tab_radgrad') break default: tab = $this.querySelector(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.classList.add('jGraduate_tab_current') tab.dispatchEvent(new Event('click')) }, 10) } </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="editor_extensions_ext-layer_view_locale_zh-CN.module_js.html">editor/extensions/ext-layer_view/locale/zh-CN.js</a></li><li><a href="module-SVGEditor.html">SVGEditor</a></li><li><a href="module-contextmenu.html">contextmenu</a></li><li><a href="module-jGraduate.html">jGraduate</a></li><li><a href="module-jPicker.html">jPicker</a></li><li><a href="module-locale.html">locale</a></li></ul><h3>Externals</h3><ul><li><a href="external-JamilihArray.html">JamilihArray</a></li><li><a href="external-Math.html">Math</a></li><li><a href="external-Window.html">Window</a></li><li><a href="external-jQuery.html">jQuery</a></li></ul><h3>Namespaces</h3><ul><li><a href="external-jQuery.fn.html">fn</a></li><li><a href="external-jQuery.fn.$.fn.jPicker.defaults.html">defaults</a></li><li><a href="external-jQuery.fn.exports.jPickerMethod.html">exports.jPickerMethod</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.html">jGraduateDefaults</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.images.html">images</a></li><li><a href="external-jQuery.fn.jGraduateDefaults.window.html">window</a></li><li><a href="external-jQuery.jGraduate.html">jGraduate</a></li><li><a href="external-jQuery.jPicker.html">jPicker</a></li><li><a href="external-jQuery.jPicker.ColorMethods.html">ColorMethods</a></li></ul><h3>Classes</h3><ul><li><a href="BottomPanel.html">BottomPanel</a></li><li><a href="Dropdown.html">Dropdown</a></li><li><a href="EditorStartup.html">EditorStartup</a></li><li><a href="ElixMenuButton.html">ElixMenuButton</a></li><li><a href="ElixNumberSpinBox.html">ElixNumberSpinBox</a></li><li><a href="ExplorerButton.html">ExplorerButton</a></li><li><a href="FlyingButton.html">FlyingButton</a></li><li><a href="LayersPanel.html">LayersPanel</a></li><li><a href="LeftPanel.html">LeftPanel</a></li><li><a href="MainMenu.html">MainMenu</a></li><li><a href="NumberSpinBox.html">NumberSpinBox</a></li><li><a href="PaintBox.html">PaintBox</a></li><li><a href="PlainNumberSpinBox.html">PlainNumberSpinBox</a></li><li><a href="Rulers.html">Rulers</a></li><li><a href="SEInput.html">SEInput</a></li><li><a href="SEPalette.html">SEPalette</a></li><li><a href="SESpinInput.html">SESpinInput</a></li><li><a href="SeCMenuDialog.html">SeCMenuDialog</a></li><li><a href="SeCMenuLayerDialog.html">SeCMenuLayerDialog</a></li><li><a href="SeColorPicker.html">SeColorPicker</a></li><li><a href="SeEditPrefsDialog.html">SeEditPrefsDialog</a></li><li><a href="SeExportDialog.html">SeExportDialog</a></li><li><a href="SeImgPropDialog.html">SeImgPropDialog</a></li><li><a href="SeList.html">SeList</a></li><li><a href="SeMenu.html">SeMenu</a></li><li><a href="SeMenuItem.html">SeMenuItem</a></li><li><a href="SePlainAlertDialog.html">SePlainAlertDialog</a></li><li><a href="SePlainBorderButton.html">SePlainBorderButton</a></li><li><a href="SePromptDialog.html">SePromptDialog</a></li><li><a href="SeStorageDialog.html">SeStorageDialog</a></li><li><a href="SeSvgSourceEditorDialog.html">SeSvgSourceEditorDialog</a></li><li><a href="SeText.html">SeText</a></li><li><a href="ToolButton.html">ToolButton</a></li><li><a href="TopPanel.html">TopPanel</a></li><li><a href="configObj.html">configObj</a></li><li><a href="external-jQuery.jGraduate.Paint.html">Paint</a></li><li><a href="external-jQuery.jPicker.Color.html">Color</a></li><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li><li><a href="module-SVGEditor-Editor.html">Editor</a></li><li><a href="module-jPicker.module.exports.html">module.exports</a></li></ul><h3>Interfaces</h3><ul><li><a href="module-SVGEditor.Config.html">Config</a></li><li><a href="module-SVGEditor.Prefs.html">Prefs</a></li><li><a href="module-SVGthis.CustomHandler.html">CustomHandler</a></li><li><a href="module-locale.LocaleEditorInit.html">LocaleEditorInit</a></li></ul><h3>Events</h3><ul><li><a href="module-SVGEditor.html#event:event:svgEditorReadyEvent">svgEditorReadyEvent</a></li></ul><h3>Tutorials</h3><ul><li><a href="tutorial-CanvasAPI.html">CanvasAPI</a></li><li><a href="tutorial-Editor.html">Editor</a></li><li><a href="tutorial-EditorAPI.html">EditorAPI</a></li><li><a href="tutorial-Events.html">Events</a></li><li><a href="tutorial-FrequentlyAskedQuestions.html">Frequently Asked Questions (FAQ)</a></li></ul><h3>Global</h3><ul><li><a href="global.html#attributeChangedCallback">attributeChangedCallback</a></li><li><a href="global.html#connectedCallback">connectedCallback</a></li><li><a href="global.html#constructor">constructor</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#decrement">decrement</a></li><li><a href="global.html#expireCookie">expireCookie</a></li><li><a href="global.html#formatValueFormatthenumericvalueasastring.Thisisusedafterincrementing/decrementingthevaluetoreformatthevalueasastring.">formatValue Format the numeric value as a string. This is used after incrementing/decrementing the value to reformat the value as a string.</a></li><li><a href="global.html#get">get</a></li><li><a href="global.html#handleClick">handleClick</a></li><li><a href="global.html#handleClose">handleClose</a></li><li><a href="global.html#handleInput">handleInput</a></li><li><a href="global.html#handleKeyDown">handleKeyDown</a></li><li><a href="global.html#handleMouseDown">handleMouseDown</a></li><li><a href="global.html#handleMouseUp">handleMouseUp</a></li><li><a href="global.html#handleOptionsChange">handleOptionsChange</a></li><li><a href="global.html#handleSelect">handleSelect</a></li><li><a href="global.html#handleShow">handleShow</a></li><li><a href="global.html#increment">increment</a></li><li><a href="global.html#init">init</a></li><li><a href="global.html#inputsize">inputsize</a></li><li><a href="global.html#isNullish">isNullish</a></li><li><a href="global.html#loadloadConfig">load load Config</a></li><li><a href="global.html#loadFromURLLoadconfig/datafromURLifgiven">loadFromURL Load config/data from URL if given</a></li><li><a href="global.html#name">name</a></li><li><a href="global.html#observedAttributes">observedAttributes</a></li><li><a href="global.html#parseValue">parseValue</a></li><li><a href="global.html#pref">pref</a></li><li><a href="global.html#readySignal">readySignal</a></li><li><a href=