UNPKG

svgedit

Version:

Powerful SVG-Editor for your browser

605 lines (525 loc) 31.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: svgcanvas/select.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: svgcanvas/select.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * DOM element selection box tools. * @module select * @license MIT * * @copyright 2010 Alexis Deveria, 2010 Jeff Schiller */ import { isTouch, isWebkit } from '../common/browser.js'; // , isOpera import { getRotationAngle, getBBox, getStrokedBBox, isNullish } from './utilities.js'; import { transformListToTransform, transformBox, transformPoint } from './math.js'; let svgFactory_; let config_; let selectorManager_; // A Singleton const gripRadius = isTouch() ? 10 : 4; /** * Private class for DOM element selection boxes. */ export class Selector { /** * @param {Integer} id - Internally identify the selector * @param {Element} elem - DOM element associated with this selector * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for initialization (prevents duplicate `getBBox` call). */ constructor(id, elem, bbox) { // this is the selector's unique number this.id = id; // this holds a reference to the element for which this selector is being used this.selectedElement = elem; // this is a flag used internally to track whether the selector is being used or not this.locked = true; // this holds a reference to the &lt;g> element that holds all visual elements of the selector this.selectorGroup = svgFactory_.createSVGElement({ element: 'g', attr: { id: ('selectorGroup' + this.id) } }); // this holds a reference to the path rect this.selectorRect = svgFactory_.createSVGElement({ element: 'path', attr: { id: ('selectedBox' + this.id), fill: 'none', stroke: '#22C', 'stroke-width': '1', 'stroke-dasharray': '5,5', // need to specify this so that the rect is not selectable style: 'pointer-events:none' } }); this.selectorGroup.append(this.selectorRect); // this holds a reference to the grip coordinates for this selector this.gripCoords = { nw: null, n: null, ne: null, e: null, se: null, s: null, sw: null, w: null }; this.reset(this.selectedElement, bbox); } /** * Used to reset the id and element that the selector is attached to. * @param {Element} e - DOM element associated with this selector * @param {module:utilities.BBoxObject} bbox - Optional bbox to use for reset (prevents duplicate getBBox call). * @returns {void} */ reset(e, bbox) { this.locked = true; this.selectedElement = e; this.resize(bbox); this.selectorGroup.setAttribute('display', 'inline'); } /** * Show the resize grips of this selector. * @param {boolean} show - Indicates whether grips should be shown or not * @returns {void} */ showGrips(show) { const bShow = show ? 'inline' : 'none'; selectorManager_.selectorGripsGroup.setAttribute('display', bShow); const elem = this.selectedElement; this.hasGrips = show; if (elem &amp;&amp; show) { this.selectorGroup.append(selectorManager_.selectorGripsGroup); Selector.updateGripCursors(getRotationAngle(elem)); } } /** * Updates the selector to match the element's size. * @param {module:utilities.BBoxObject} [bbox] - BBox to use for resize (prevents duplicate getBBox call). * @returns {void} */ resize(bbox) { const dataStorage = svgFactory_.getDataStorage(); const selectedBox = this.selectorRect; const mgr = selectorManager_; const selectedGrips = mgr.selectorGrips; const selected = this.selectedElement; const sw = selected.getAttribute('stroke-width'); const currentZoom = svgFactory_.getCurrentZoom(); let offset = 1 / currentZoom; if (selected.getAttribute('stroke') !== 'none' &amp;&amp; !isNaN(sw)) { offset += (sw / 2); } const { tagName } = selected; if (tagName === 'text') { offset += 2 / currentZoom; } // loop and transform our bounding box until we reach our first rotation const tlist = selected.transform.baseVal; const m = transformListToTransform(tlist).matrix; // This should probably be handled somewhere else, but for now // it keeps the selection box correctly positioned when zoomed m.e *= currentZoom; m.f *= currentZoom; if (!bbox) { bbox = getBBox(selected); } // TODO: getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this? // TODO: getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated? if (tagName === 'g' &amp;&amp; !dataStorage.has(selected, 'gsvg')) { // The bbox for a group does not include stroke vals, so we // get the bbox based on its children. const strokedBbox = getStrokedBBox([ selected.childNodes ]); if (strokedBbox) { bbox = strokedBbox; } } // apply the transforms const l = bbox.x; const t = bbox.y; const w = bbox.width; const h = bbox.height; // bbox = {x: l, y: t, width: w, height: h}; // Not in use // we need to handle temporary transforms too // if skewed, get its transformed box, then find its axis-aligned bbox // * offset *= currentZoom; const nbox = transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m); const { aabox } = nbox; let nbax = aabox.x - offset; let nbay = aabox.y - offset; let nbaw = aabox.width + (offset * 2); let nbah = aabox.height + (offset * 2); // now if the shape is rotated, un-rotate it const cx = nbax + nbaw / 2; const cy = nbay + nbah / 2; const angle = getRotationAngle(selected); if (angle) { const rot = svgFactory_.svgRoot().createSVGTransform(); rot.setRotate(-angle, cx, cy); const rotm = rot.matrix; nbox.tl = transformPoint(nbox.tl.x, nbox.tl.y, rotm); nbox.tr = transformPoint(nbox.tr.x, nbox.tr.y, rotm); nbox.bl = transformPoint(nbox.bl.x, nbox.bl.y, rotm); nbox.br = transformPoint(nbox.br.x, nbox.br.y, rotm); // calculate the axis-aligned bbox const { tl } = nbox; let minx = tl.x; let miny = tl.y; let maxx = tl.x; let maxy = tl.y; const { min, max } = Math; minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset; miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset; maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset; maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset; nbax = minx; nbay = miny; nbaw = (maxx - minx); nbah = (maxy - miny); } const dstr = 'M' + nbax + ',' + nbay + ' L' + (nbax + nbaw) + ',' + nbay + ' ' + (nbax + nbaw) + ',' + (nbay + nbah) + ' ' + nbax + ',' + (nbay + nbah) + 'z'; selectedBox.setAttribute('d', dstr); const xform = angle ? 'rotate(' + [ angle, cx, cy ].join(',') + ')' : ''; this.selectorGroup.setAttribute('transform', xform); // TODO(codedread): Is this needed? // if (selected === selectedElements[0]) { this.gripCoords = { nw: [ nbax, nbay ], ne: [ nbax + nbaw, nbay ], sw: [ nbax, nbay + nbah ], se: [ nbax + nbaw, nbay + nbah ], n: [ nbax + (nbaw) / 2, nbay ], w: [ nbax, nbay + (nbah) / 2 ], e: [ nbax + nbaw, nbay + (nbah) / 2 ], s: [ nbax + (nbaw) / 2, nbay + nbah ] }; Object.entries(this.gripCoords).forEach(([ dir, coords ]) => { selectedGrips[dir].setAttribute('cx', coords[0]); selectedGrips[dir].setAttribute('cy', coords[1]); }); // we want to go 20 pixels in the negative transformed y direction, ignoring scale mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2); mgr.rotateGripConnector.setAttribute('y1', nbay); mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2); mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5)); mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2); mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5)); // } } // STATIC methods /** * Updates cursors for corner grips on rotation so arrows point the right way. * @param {Float} angle - Current rotation angle in degrees * @returns {void} */ static updateGripCursors(angle) { const dirArr = Object.keys(selectorManager_.selectorGrips); let steps = Math.round(angle / 45); if (steps &lt; 0) { steps += 8; } while (steps > 0) { dirArr.push(dirArr.shift()); steps--; } Object.values(selectorManager_.selectorGrips).forEach((gripElement, i) => { gripElement.setAttribute('style', ('cursor:' + dirArr[i] + '-resize')); }); } } /** * Manage all selector objects (selection boxes). */ export class SelectorManager { /** * Sets up properties and calls `initGroup`. */ constructor() { // this will hold the &lt;g> element that contains all selector rects/grips this.selectorParentGroup = null; // this is a special rect that is used for multi-select this.rubberBandBox = null; // this will hold objects of type Selector (see above) this.selectors = []; // this holds a map of SVG elements to their Selector object this.selectorMap = {}; // this holds a reference to the grip elements this.selectorGrips = { nw: null, n: null, ne: null, e: null, se: null, s: null, sw: null, w: null }; this.selectorGripsGroup = null; this.rotateGripConnector = null; this.rotateGrip = null; this.initGroup(); } /** * Resets the parent selector group element. * @returns {void} */ initGroup() { const dataStorage = svgFactory_.getDataStorage(); // remove old selector parent group if it existed if (this.selectorParentGroup &amp;&amp; this.selectorParentGroup.parentNode) { this.selectorParentGroup.remove(); } // create parent selector group and add it to svgroot this.selectorParentGroup = svgFactory_.createSVGElement({ element: 'g', attr: { id: 'selectorParentGroup' } }); this.selectorGripsGroup = svgFactory_.createSVGElement({ element: 'g', attr: { display: 'none' } }); this.selectorParentGroup.append(this.selectorGripsGroup); svgFactory_.svgRoot().append(this.selectorParentGroup); this.selectorMap = {}; this.selectors = []; this.rubberBandBox = null; // add the corner grips Object.keys(this.selectorGrips).forEach((dir) => { const grip = svgFactory_.createSVGElement({ element: 'circle', attr: { id: ('selectorGrip_resize_' + dir), fill: '#22C', r: gripRadius, style: ('cursor:' + dir + '-resize'), // This expands the mouse-able area of the grips making them // easier to grab with the mouse. // This works in Opera and WebKit, but does not work in Firefox // see https://bugzilla.mozilla.org/show_bug.cgi?id=500174 'stroke-width': 2, 'pointer-events': 'all' } }); dataStorage.put(grip, 'dir', dir); dataStorage.put(grip, 'type', 'resize'); this.selectorGrips[dir] = grip; this.selectorGripsGroup.append(grip); }); // add rotator elems this.rotateGripConnector = svgFactory_.createSVGElement({ element: 'line', attr: { id: ('selectorGrip_rotateconnector'), stroke: '#22C', 'stroke-width': '1' } }); this.selectorGripsGroup.append(this.rotateGripConnector); this.rotateGrip = svgFactory_.createSVGElement({ element: 'circle', attr: { id: 'selectorGrip_rotate', fill: 'lime', r: gripRadius, stroke: '#22C', 'stroke-width': 2, style: `cursor:url(${config_.imgPath}/rotate.svg) 12 12, auto;` } }); this.selectorGripsGroup.append(this.rotateGrip); dataStorage.put(this.rotateGrip, 'type', 'rotate'); if (document.getElementById('canvasBackground')) { return; } const [ width, height ] = config_.dimensions; const canvasbg = svgFactory_.createSVGElement({ element: 'svg', attr: { id: 'canvasBackground', width, height, x: 0, y: 0, overflow: (isWebkit() ? 'none' : 'visible'), // Chrome 7 has a problem with this when zooming out style: 'pointer-events:none' } }); const rect = svgFactory_.createSVGElement({ element: 'rect', attr: { width: '100%', height: '100%', x: 0, y: 0, 'stroke-width': 1, stroke: '#000', fill: '#FFF', style: 'pointer-events:none' } }); // Both Firefox and WebKit are too slow with this filter region (especially at higher // zoom levels) and Opera has at least one bug // if (!isOpera()) rect.setAttribute('filter', 'url(#canvashadow)'); canvasbg.append(rect); svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); // Ok to replace above with `svgFactory_.svgContent().before(canvasbg);`? } /** * * @param {Element} elem - DOM element to get the selector for * @param {module:utilities.BBoxObject} [bbox] - Optional bbox to use for reset (prevents duplicate getBBox call). * @returns {Selector} The selector based on the given element */ requestSelector(elem, bbox) { if (isNullish(elem)) { return null; } const N = this.selectors.length; // If we've already acquired one for this element, return it. if (typeof this.selectorMap[elem.id] === 'object') { this.selectorMap[elem.id].locked = true; return this.selectorMap[elem.id]; } for (let i = 0; i &lt; N; ++i) { if (this.selectors[i] &amp;&amp; !this.selectors[i].locked) { this.selectors[i].locked = true; this.selectors[i].reset(elem, bbox); this.selectorMap[elem.id] = this.selectors[i]; return this.selectors[i]; } } // if we reached here, no available selectors were found, we create one this.selectors[N] = new Selector(N, elem, bbox); this.selectorParentGroup.append(this.selectors[N].selectorGroup); this.selectorMap[elem.id] = this.selectors[N]; return this.selectors[N]; } /** * Removes the selector of the given element (hides selection box). * * @param {Element} elem - DOM element to remove the selector for * @returns {void} */ releaseSelector(elem) { if (isNullish(elem)) { return; } const N = this.selectors.length; const sel = this.selectorMap[elem.id]; if (sel &amp;&amp; !sel.locked) { // TODO(codedread): Ensure this exists in this module. console.warn('WARNING! selector was released but was already unlocked'); } for (let i = 0; i &lt; N; ++i) { if (this.selectors[i] &amp;&amp; this.selectors[i] === sel) { delete this.selectorMap[elem.id]; sel.locked = false; sel.selectedElement = null; sel.showGrips(false); // remove from DOM and store reference in JS but only if it exists in the DOM try { sel.selectorGroup.setAttribute('display', 'none'); } catch (e) {/* empty fn */ } break; } } } /** * @returns {SVGRectElement} The rubberBandBox DOM element. This is the rectangle drawn by * the user for selecting/zooming */ getRubberBandBox() { if (!this.rubberBandBox) { this.rubberBandBox = svgFactory_.createSVGElement({ element: 'rect', attr: { id: 'selectorRubberBand', fill: '#22C', 'fill-opacity': 0.15, stroke: '#22C', 'stroke-width': 0.5, display: 'none', style: 'pointer-events:none' } }); this.selectorParentGroup.append(this.rubberBandBox); } return this.rubberBandBox; } } /** * An object that creates SVG elements for the canvas. * * @interface module:select.SVGFactory */ /** * @function module:select.SVGFactory#createSVGElement * @param {module:utilities.EditorContext#addSVGElementFromJson} jsonMap * @returns {SVGElement} */ /** * @function module:select.SVGFactory#svgRoot * @returns {SVGSVGElement} */ /** * @function module:select.SVGFactory#svgContent * @returns {SVGSVGElement} */ /** * @function module:select.SVGFactory#getCurrentZoom * @returns {Float} The current zoom level */ /** * @typedef {GenericArray} module:select.Dimensions * @property {Integer} length 2 * @property {Float} 0 Width * @property {Float} 1 Height */ /** * @typedef {PlainObject} module:select.Config * @property {string} imgPath * @property {module:select.Dimensions} dimensions */ /** * Initializes this module. * @function module:select.init * @param {module:select.Config} config - An object containing configurable parameters (imgPath) * @param {module:select.SVGFactory} svgFactory - An object implementing the SVGFactory interface. * @returns {void} */ export const init = function (config, svgFactory) { config_ = config; svgFactory_ = svgFactory; selectorManager_ = new SelectorManager(); }; /** * @function module:select.getSelectorManager * @returns {module:select.SelectorManager} The SelectorManager instance. */ export const getSelectorManager = () => selectorManager_; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-blur.html">blur</a></li><li><a href="module-browser.html">browser</a></li><li><a href="module-clear.html">clear</a></li><li><a href="module-contextmenu.html">contextmenu</a></li><li><a href="module-coords.html">coords</a></li><li><a href="module-draw.html">draw</a></li><li><a href="module-elem-get-set%2520get%2520and%2520set%2520methods..html">elem-get-set get and set methods.</a></li><li><a href="module-event.html">event</a></li><li><a href="module-history.html">history</a></li><li><a href="module-jGraduate.html">jGraduate</a></li><li><a href="module-jPicker.html">jPicker</a></li><li><a href="module-jQueryAttr.html">jQueryAttr</a></li><li><a href="module-layer.html">layer</a></li><li><a href="module-locale.html">locale</a></li><li><a href="module-math.html">math</a></li><li><a href="module-namespaces.html">namespaces</a></li><li><a href="module-path.html">path</a></li><li><a href="module-recalculate.html">recalculate</a></li><li><a href="module-sanitize.html">sanitize</a></li><li><a href="module-select.html">select</a></li><li><a href="module-selected-elem.html">selected-elem</a></li><li><a href="module-selection.html">selection</a></li><li><a href="module-svg.html">svg</a></li><li><a href="module-svgcanvas.html">svgcanvas</a></li><li><a href="module-SVGEditor.html">SVGEditor</a></li><li><a href="module-text-actions%2520Tools%2520for%2520Text%2520edit%2520functions.html">text-actions Tools for Text edit functions</a></li><li><a href="module-undo.html">undo</a></li><li><a href="module-units.html">units</a></li><li><a href="module-utilities.html">utilities</a></li></ul><h3>Externals</h3><ul><li><a href="external-JamilihArray.html">JamilihArray</a></li><li><a href="external-jQuery.html">jQuery</a></li><li><a href="external-Math.html">Math</a></li><li><a href="external-MouseEvent.html">MouseEvent</a></li><li><a href="external-Window.html">Window</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><li><a href="module-path.html#.pathActions">pathActions</a></li><li><a href="module-svgcanvas.SvgCanvas_pathActions.html">pathActions</a></li><li><a href="module-svgcanvas.SvgCanvas_textActions.html">textActions</a></li></ul><h3>Classes</h3><ul><li><a href="BottomPanel.html">BottomPanel</a></li><li><a href="configObj.html">configObj</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="external-jQuery.jGraduate.Paint.html">Paint</a></li><li><a href="external-jQuery.jPicker.Color.html">Color</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="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li><li><a href="module-draw.Drawing.html">Drawing</a></li><li><a href="module-draw.Layer.html">Layer</a></li><li><a href="module-history.BatchCommand.html">BatchCommand</a></li><li><a href="module-history.ChangeElementCommand.html">ChangeElementCommand</a></li><li><a href="module-history.Command.html">Command</a></li><li><a href="module-history.HistoryRecordingService.html">HistoryRecordingService</a></li><li><a href="module-history.InsertElementCommand.html">InsertElementCommand</a></li><li><a href="module-history.MoveElementCommand.html">MoveElementCommand</a></li><li><a href="module-history.RemoveElementCommand.html">RemoveElementCommand</a></li><li><a href="module-history.UndoManager.html">UndoManager</a></li><li><a href="module-jPicker.module.exports.html">module.exports</a></li><li><a href="module-layer.Layer.html">Layer</a></li><li><a href="module-path.Path.html">Path</a></li><li><a href="module-path.Segment.html">Segment</a></li><li><a href="module-select.Selector.html">Selector</a></li><li><a href="module-select.SelectorManager.html">SelectorManager</a></li><li><a href="module-svgcanvas.SvgCanvas.html">SvgCanvas</a></li><li><a href="module-SVGEditor-Editor.html">Editor</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="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="SEInput.html">SEInput</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="SEPalette.html">SEPalette</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="SESpinInput.html">SESpinInput</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></ul><h3>Interfaces</h3><ul><li><a href="module-coords.EditorContext.html">EditorContext</a></li><li><a href="module-draw.DrawCanvasInit.html">DrawCanvasInit</a></li><li><a href="module-history.HistoryCommand.html">HistoryCommand</a></li><li><a href="module-history.HistoryEventHandler.html">HistoryEventHandler</a></li><li><a href="module-locale.LocaleEditorInit.html">LocaleEditorInit</a></li><li><a href="module-path.EditorContext.html">EditorContext</a></li><li><a href="module-recalculate.EditorContext.html">EditorContext</a></li><li><a href="module-select.SVGFactory.html">SVGFactory</a></li><li><a href="module-svgcanvas.PrivateMethods.html">PrivateMethods</a></li><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-units.ElementContainer.html">ElementContainer</a></li><li><a href="module-utilities.EditorContext.html">EditorContext</a></li></ul><h3>Events</h3><ul><li><a href="module-history-Command.html#event:event:history">history</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:changed">changed</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:cleared">cleared</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:contextset">contextset</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:exported">exported</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:exportedPDF">exportedPDF</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_addLangData">ext_addLangData</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_callback">ext_callback</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_canvasUpdated">ext_canvasUpdated</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_elementChanged">ext_elementChanged</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_elementTransition">ext_elementTransition</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_IDsUpdated">ext_IDsUpdated</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_langChanged">ext_langChanged</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_langReady">ext_langReady</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_mouseDown">ext_mouseDown</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_mouseMove">ext_mouseMove</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_mouseUp">ext_mouseUp</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_onNewDocument">ext_onNewDocument</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_selectedChanged">ext_selectedChanged</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_toolButtonStateUpdate">ext_toolButtonStateUpdate</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_workareaResized">ext_workareaResized</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:ext_zoomChanged">ext_zoomChanged</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:extension_added">extension_added</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:extensions_added">extensions_added</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:GenericCanvasEvent">GenericCanvasEvent</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:message">message</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:pointsAdded">pointsAdded</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:saved">saved</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:selected">selected</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:setnonce">setnonce</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:transition">transition</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:unsetnonce">unsetnonce</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:updateCanvas">updateCanvas</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:zoomDone">zoomDone</a></li><li><a href="module-svgcanvas.SvgCanvas.html#event:event:zoomed">zoomed</a></li><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#expireCookie">expireCookie</a></li><li><a href="global.html#findPos">findPos</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#getClosest">getClosest</a></li><li><a href="global.html#getParents">getParents</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#processResults">processResults</a></li><li><a href="global.html#readySignal">readySignal</a></li><li><a href="global.html#regexEscape">regexEscape</a></li><li><a href="global.html#removeStoragePrefCookie">removeStoragePrefCookie</a></li><li><a href="global.html#replaceStoragePrompt">replaceStoragePrompt</a></li><li><a href="global.html#set">set</a></li><li><a href="global.html#setupCurConfig">setupCurConfig</a></li><li><a href="global.html#setupCurPrefs">setupCurPrefs</a></li><li><a href="global.html#src">src</a></li><li><a href="global.html#stateEffects">stateEffects</a></li><li><a href="global.html#stepDown">stepDown</a></li><li><a href="global.html#stepUp">stepUp</a></li><li><a href="global.html#touchHandler">touchHandler</a></li><li><a href="global.html#updateLib">updateLib</a></li><li><a href="global.html#value">value</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.7</a> on Mon Nov 08 2021 09:47:00 GMT+0100 (Central European Standard Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>