svgedit
Version:
Powerful SVG-Editor for your browser
854 lines (767 loc) • 42.2 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: editor/EditorStartup.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: editor/EditorStartup.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/* globals seConfirm seAlert */
import './touch.js';
import { convertUnit } from '../common/units.js';
import {
putLocale
} from './locale.js';
import {
hasCustomHandler, getCustomHandler, injectExtendedContextMenuItemsIntoDom
} from './contextmenu.js';
import editorTemplate from './templates/editorTemplate.js';
import SvgCanvas from '../svgcanvas/svgcanvas.js';
import Rulers from './Rulers.js';
/**
* @fires module:svgcanvas.SvgCanvas#event:svgEditorReady
* @returns {void}
*/
const readySignal = () => {
// let the opener know SVG Edit is ready (now that config is set up)
const w = window.opener || window.parent;
if (w) {
try {
/**
* Triggered on a containing `document` (of `window.opener`
* or `window.parent`) when the editor is loaded.
* @event module:SVGEditor#event:svgEditorReadyEvent
* @type {Event}
* @property {true} bubbles
* @property {true} cancelable
*/
/**
* @name module:SVGthis.svgEditorReadyEvent
* @type {module:SVGEditor#event:svgEditorReadyEvent}
*/
const svgEditorReadyEvent = new w.CustomEvent('svgEditorReady', {
bubbles: true,
cancelable: true
});
w.document.documentElement.dispatchEvent(svgEditorReadyEvent);
} catch (e) {/* empty fn */}
}
};
const { $id, $qq } = SvgCanvas;
/**
*
*/
class EditorStartup {
/**
*
*/
constructor (div) {
this.extensionsAdded = false;
this.messageQueue = [];
this.$container = div??$id('svg_editor');
}
/**
* Auto-run after a Promise microtask.
* @function module:SVGthis.init
* @returns {void}
*/
async init () {
if ('localStorage' in window) {
this.storage = window.localStorage;
}
this.configObj.load();
const { i18next } = await putLocale(this.configObj.pref('lang'), this.goodLangs);
this.i18next = i18next;
await import(`./components/index.js`);
await import(`./dialogs/index.js`);
try {
// add editor components to the DOM
this.$container.append(editorTemplate.content.cloneNode(true));
this.$svgEditor = $qq('.svg_editor');
// allow to prepare the dom without display
this.$svgEditor.style.visibility = 'hidden';
this.workarea = $id('workarea');
// Image props dialog added to DOM
const newSeImgPropDialog = document.createElement('se-img-prop-dialog');
newSeImgPropDialog.setAttribute('id', 'se-img-prop');
this.$container.append(newSeImgPropDialog);
newSeImgPropDialog.init(this.i18next);
// editor prefences dialoag added to DOM
const newSeEditPrefsDialog = document.createElement('se-edit-prefs-dialog');
newSeEditPrefsDialog.setAttribute('id', 'se-edit-prefs');
this.$container.append(newSeEditPrefsDialog);
newSeEditPrefsDialog.init(this.i18next);
// canvas menu added to DOM
const dialogBox = document.createElement('se-cmenu_canvas-dialog');
dialogBox.setAttribute('id', 'se-cmenu_canvas');
this.$container.append(dialogBox);
dialogBox.init(this.i18next);
// alertDialog added to DOM
const alertBox = document.createElement('se-alert-dialog');
alertBox.setAttribute('id', 'se-alert-dialog');
this.$container.append(alertBox);
// promptDialog added to DOM
const promptBox = document.createElement('se-prompt-dialog');
promptBox.setAttribute('id', 'se-prompt-dialog');
this.$container.append(promptBox);
// Export dialog added to DOM
const exportDialog = document.createElement('se-export-dialog');
exportDialog.setAttribute('id', 'se-export-dialog');
this.$container.append(exportDialog);
exportDialog.init(this.i18next);
} catch (err) {
console.error(err);
}
/**
* @name module:SVGthis.canvas
* @type {module:svgcanvas.SvgCanvas}
*/
this.svgCanvas = new SvgCanvas(
$id('svgcanvas'),
this.configObj.curConfig
);
this.leftPanel.init();
this.bottomPanel.init();
this.topPanel.init();
this.layersPanel.init();
this.mainMenu.init();
const { undoMgr } = this.svgCanvas;
this.canvMenu = $id('se-cmenu_canvas');
this.exportWindow = null;
this.defaultImageURL = `${this.configObj.curConfig.imgPath}/logo.svg`;
const zoomInIcon = 'crosshair';
const zoomOutIcon = 'crosshair';
this.uiContext = 'toolbars';
// For external openers
readySignal();
this.rulers = new Rulers(this);
this.layersPanel.populateLayers();
this.selectedElement = null;
this.multiselected = false;
const aLink = $id('cur_context_panel');
aLink.addEventListener('click', (evt) => {
const link = evt.target;
if (link.hasAttribute('data-root')) {
this.svgCanvas.leaveContext();
} else {
this.svgCanvas.setContext(link.textContent);
}
this.svgCanvas.clearSelection();
return false;
});
// bind the selected event to our function that handles updates to the UI
this.svgCanvas.bind('selected', this.selectedChanged.bind(this));
this.svgCanvas.bind('transition', this.elementTransition.bind(this));
this.svgCanvas.bind('changed', this.elementChanged.bind(this));
this.svgCanvas.bind('exported', this.exportHandler.bind(this));
this.svgCanvas.bind('exportedPDF', function (win, data) {
if (!data.output) { // Ignore Chrome
return;
}
const { exportWindowName } = data;
if (exportWindowName) {
this.exportWindow = window.open('', this.exportWindowName); // A hack to get the window via JSON-able name without opening a new one
}
if (!this.exportWindow || this.exportWindow.closed) {
seAlert(this.i18next.t('notification.popupWindowBlocked'));
return;
}
this.exportWindow.location.href = data.output;
}.bind(this));
this.svgCanvas.bind('zoomed', this.zoomChanged.bind(this));
this.svgCanvas.bind('zoomDone', this.zoomDone.bind(this));
this.svgCanvas.bind(
'updateCanvas',
/**
* @param {external:Window} win
* @param {PlainObject} centerInfo
* @param {false} centerInfo.center
* @param {module:math.XYObject} centerInfo.newCtr
* @listens module:svgcanvas.SvgCanvas#event:updateCanvas
* @returns {void}
*/
function (win, { center, newCtr }) {
this.updateCanvas(center, newCtr);
}.bind(this)
);
this.svgCanvas.bind('contextset', this.contextChanged.bind(this));
this.svgCanvas.bind('extension_added', this.extAdded.bind(this));
this.svgCanvas.textActions.setInputElem($id('text'));
this.setBackground(this.configObj.pref('bkgd_color'), this.configObj.pref('bkgd_url'));
// update resolution option with actual resolution
const res = this.svgCanvas.getResolution();
if (this.configObj.curConfig.baseUnit !== 'px') {
res.w = convertUnit(res.w) + this.configObj.curConfig.baseUnit;
res.h = convertUnit(res.h) + this.configObj.curConfig.baseUnit;
}
$id('se-img-prop').setAttribute('dialog', 'close');
$id('se-img-prop').setAttribute('title', this.svgCanvas.getDocumentTitle());
$id('se-img-prop').setAttribute('width', res.w);
$id('se-img-prop').setAttribute('height', res.h);
$id('se-img-prop').setAttribute('save', this.configObj.pref('img_save'));
// Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
const selElements = document.querySelectorAll("select");
Array.from(selElements).forEach(function(element) {
element.addEventListener('change', function(evt) {
evt.currentTarget.blur();
});
});
// fired when user wants to move elements to another layer
let promptMoveLayerOnce = false;
$id('selLayerNames').addEventListener('change', (evt) => {
const destLayer = evt.detail.value;
const confirmStr = this.i18next.t('notification.QmoveElemsToLayer').replace('%s', destLayer);
/**
* @param {boolean} ok
* @returns {void}
*/
const moveToLayer = (ok) => {
if (!ok) { return; }
promptMoveLayerOnce = true;
this.svgCanvas.moveSelectedToLayer(destLayer);
this.svgCanvas.clearSelection();
this.layersPanel.populateLayers();
};
if (destLayer) {
if (promptMoveLayerOnce) {
moveToLayer(true);
} else {
const ok = seConfirm(confirmStr);
if (!ok) {
return;
}
moveToLayer(true);
}
}
});
$id('tool_font_family').addEventListener('change', (evt) => {
this.svgCanvas.setFontFamily(evt.detail.value);
});
$id('seg_type').addEventListener('change', (evt) => {
this.svgCanvas.setSegType(evt.detail.value);
});
const addListenerMulti = (element, eventNames, listener)=> {
eventNames.split(' ').forEach((eventName)=> element.addEventListener(eventName, listener, false));
};
addListenerMulti($id('text'), 'keyup input', (evt) => {
this.svgCanvas.setTextContent(evt.currentTarget.value);
});
$id('link_url').addEventListener('change', (evt) => {
if (evt.currentTarget.value.length) {
this.svgCanvas.setLinkURL(evt.currentTarget.value);
} else {
this.svgCanvas.removeHyperlink();
}
});
$id('g_title').addEventListener('change', (evt) => {
this.svgCanvas.setGroupTitle(evt.currentTarget.value);
});
let lastX = null; let lastY = null;
let panning = false; let keypan = false;
$id('svgcanvas').addEventListener('mouseup', (evt) => {
if (panning === false) { return true; }
this.workarea.scrollLeft -= (evt.clientX - lastX);
this.workarea.scrollTop -= (evt.clientY - lastY);
lastX = evt.clientX;
lastY = evt.clientY;
if (evt.type === 'mouseup') { panning = false; }
return false;
});
$id('svgcanvas').addEventListener('mousemove', (evt) => {
if (panning === false) { return true; }
this.workarea.scrollLeft -= (evt.clientX - lastX);
this.workarea.scrollTop -= (evt.clientY - lastY);
lastX = evt.clientX;
lastY = evt.clientY;
if (evt.type === 'mouseup') { panning = false; }
return false;
});
$id('svgcanvas').addEventListener('mousedown', (evt) => {
if (evt.button === 1 || keypan === true) {
panning = true;
lastX = evt.clientX;
lastY = evt.clientY;
return false;
}
return true;
});
window.addEventListener('mouseup', () => {
panning = false;
});
document.addEventListener('keydown', (e) => {
if (e.target.nodeName !== 'BODY') return;
if(e.code.toLowerCase() === 'space'){
this.svgCanvas.spaceKey = keypan = true;
e.preventDefault();
} else if((e.key.toLowerCase() === 'shift') && (this.svgCanvas.getMode() === 'zoom')){
this.workarea.style.cursor = zoomOutIcon;
e.preventDefault();
} else {
return;
}
});
document.addEventListener('keyup', (e) => {
if (e.target.nodeName !== 'BODY') return;
if(e.code.toLowerCase() === 'space'){
this.svgCanvas.spaceKey = keypan = false;
e.preventDefault();
} else if((e.key.toLowerCase() === 'shift') && (this.svgCanvas.getMode() === 'zoom')){
this.workarea.style.cursor = zoomInIcon;
e.preventDefault();
} else {
return;
}
});
/**
* @function module:SVGthis.setPanning
* @param {boolean} active
* @returns {void}
*/
this.setPanning = (active) => {
this.svgCanvas.spaceKey = keypan = active;
};
let inp;
/**
*
* @returns {void}
*/
const unfocus = () => {
inp.blur();
};
const liElems = this.$svgEditor.querySelectorAll('button, select, input:not(#text)');
const self = this;
Array.prototype.forEach.call(liElems, function(el){
el.addEventListener("focus", (e) => {
inp = e.currentTarget;
self.uiContext = 'toolbars';
self.workarea.addEventListener('mousedown', unfocus);
});
el.addEventListener("blur", () => {
self.uiContext = 'canvas';
self.workarea.removeEventListener('mousedown', unfocus);
// Go back to selecting text if in textedit mode
if (self.svgCanvas.getMode() === 'textedit') {
$id('text').focus();
}
});
});
// ref: https://stackoverflow.com/a/1038781
function getWidth() {
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}
function getHeight() {
return Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
}
const winWh = {
width: getWidth(),
height: getHeight()
};
window.addEventListener('resize', () => {
Object.entries(winWh).forEach(([ type, val ]) => {
const curval = (type === 'width') ? window.innerWidth - 15 : window.innerHeight;
this.workarea['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
winWh[type] = curval;
});
});
this.workarea.addEventListener('scroll', () => {
this.rulers.manageScroll();
});
$id('stroke_width').value = this.configObj.curConfig.initStroke.width;
$id('opacity').value = this.configObj.curConfig.initOpacity * 100;
const elements = document.getElementsByClassName("push_button");
Array.from(elements).forEach(function(element) {
element.addEventListener('mousedown', function(event) {
if (!event.currentTarget.classList.contains('disabled')) {
event.currentTarget.classList.add('push_button_pressed');
event.currentTarget.classList.remove('push_button');
}
});
element.addEventListener('mouseout', function(event) {
event.currentTarget.classList.add('push_button');
event.currentTarget.classList.remove('push_button_pressed');
});
element.addEventListener('mouseup', function(event) {
event.currentTarget.classList.add('push_button');
event.currentTarget.classList.remove('push_button_pressed');
});
});
this.layersPanel.populateLayers();
const centerCanvas = () => {
// this centers the canvas vertically in the this.workarea (horizontal handled in CSS)
this.workarea.style.lineHeight = this.workarea.style.height;
};
addListenerMulti(window, 'load resize', centerCanvas);
// Prevent browser from erroneously repopulating fields
const inputEles = document.querySelectorAll('input');
Array.from(inputEles).forEach(function(inputEle) {
inputEle.setAttribute('autocomplete', 'off');
});
const selectEles = document.querySelectorAll('select');
Array.from(selectEles).forEach(function(inputEle) {
inputEle.setAttribute('autocomplete', 'off');
});
$id('se-svg-editor-dialog').addEventListener('change', function (e) {
if (e?.detail?.copy === 'click') {
this.cancelOverlays(e);
} else if (e?.detail?.dialog === 'closed') {
this.hideSourceEditor();
} else {
this.saveSourceEditor(e);
}
}.bind(this));
$id('se-cmenu_canvas').addEventListener('change', function (e) {
const action = e?.detail?.trigger;
switch (action) {
case 'delete':
this.svgCanvas.deleteSelectedElements();
break;
case 'cut':
this.cutSelected();
break;
case 'copy':
this.copySelected();
break;
case 'paste':
this.svgCanvas.pasteElements();
break;
case 'paste_in_place':
this.svgCanvas.pasteElements('in_place');
break;
case 'group':
case 'group_elements':
this.svgCanvas.groupSelectedElements();
break;
case 'ungroup':
this.svgCanvas.ungroupSelectedElement();
break;
case 'move_front':
this.svgCanvas.moveToTopSelectedElement();
break;
case 'move_up':
this.moveUpDownSelected('Up');
break;
case 'move_down':
this.moveUpDownSelected('Down');
break;
case 'move_back':
this.svgCanvas.moveToBottomSelectedElement();
break;
default:
if (hasCustomHandler(action)) {
getCustomHandler(action).call();
}
break;
}
}.bind(this));
// Select given tool
this.ready(function () {
const preTool = $id(`tool_${this.configObj.curConfig.initTool}`);
const regTool = $id(this.configObj.curConfig.initTool);
const selectTool = $id('tool_select');
const $editDialog = $id('se-edit-prefs');
if (preTool) {
preTool.click();
} else if (regTool) {
regTool.click();
} else {
selectTool.click();
}
if (this.configObj.curConfig.wireframe) {
$id('tool_wireframe').click();
}
if (this.configObj.curConfig.showRulers) {
this.rulers.display(true);
} else {
this.rulers.display(false);
}
if (this.configObj.curConfig.showRulers) {
$editDialog.setAttribute('showrulers', true);
}
if (this.configObj.curConfig.baseUnit) {
$editDialog.setAttribute('baseunit', this.configObj.curConfig.baseUnit);
}
if (this.configObj.curConfig.gridSnapping) {
$editDialog.setAttribute('gridsnappingon', true);
}
if (this.configObj.curConfig.snappingStep) {
$editDialog.setAttribute('gridsnappingstep', this.configObj.curConfig.snappingStep);
}
if (this.configObj.curConfig.gridColor) {
$editDialog.setAttribute('gridcolor', this.configObj.curConfig.gridColor);
}
}.bind(this));
// zoom
$id('zoom').value = (this.svgCanvas.getZoom() * 100).toFixed(1);
this.canvMenu.setAttribute('disableallmenu', true);
this.canvMenu.setAttribute('enablemenuitems', '#delete,#cut,#copy');
this.enableOrDisableClipboard();
window.addEventListener('storage', function (e) {
if (e.key !== 'svgedit_clipboard') { return; }
this.enableOrDisableClipboard();
}.bind(this));
window.addEventListener('beforeunload', function (e) {
// Suppress warning if page is empty
if (undoMgr.getUndoStackSize() === 0) {
this.showSaveWarning = false;
}
// showSaveWarning is set to 'false' when the page is saved.
if (!this.configObj.curConfig.no_save_warning && this.showSaveWarning) {
// Browser already asks question about closing the page
e.returnValue = this.i18next.t('notification.unsavedChanges'); // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
return this.i18next.t('notification.unsavedChanges');
}
return true;
}.bind(this));
// Use HTML5 File API: http://www.w3.org/TR/FileAPI/
// if browser has HTML5 File API support, then we will show the open menu item
// and provide a file input to click. When that change event fires, it will
// get the text contents of the file and send it to the canvas
if (window.FileReader) {
/**
* @param {Event} e
* @returns {void}
*/
const editorObj = this;
const importImage = function (e) {
$id('se-prompt-dialog').title = editorObj.i18next.t('notification.loadingImage');
e.stopPropagation();
e.preventDefault();
const file = (e.type === 'drop') ? e.dataTransfer.files[0] : this.files[0];
if (!file) {
$id('se-prompt-dialog').setAttribute('close', true);
return;
}
if (!file.type.includes('image')) {
return;
}
// Detected an image
// svg handling
let reader;
if (file.type.includes('svg')) {
reader = new FileReader();
reader.onloadend = function (ev) {
const newElement = editorObj.svgCanvas.importSvgString(ev.target.result, true);
editorObj.svgCanvas.ungroupSelectedElement();
editorObj.svgCanvas.ungroupSelectedElement();
editorObj.svgCanvas.groupSelectedElements();
editorObj.svgCanvas.alignSelectedElements('m', 'page');
editorObj.svgCanvas.alignSelectedElements('c', 'page');
// highlight imported element, otherwise we get strange empty selectbox
editorObj.svgCanvas.selectOnly([ newElement ]);
$id('se-prompt-dialog').setAttribute('close', true);
};
reader.readAsText(file);
} else {
// bitmap handling
reader = new FileReader();
reader.onloadend = function ({ target: { result } }) {
/**
* Insert the new image until we know its dimensions.
* @param {Float} imageWidth
* @param {Float} imageHeight
* @returns {void}
*/
const insertNewImage = function (imageWidth, imageHeight) {
const newImage = editorObj.svgCanvas.addSVGElementFromJson({
element: 'image',
attr: {
x: 0,
y: 0,
width: imageWidth,
height: imageHeight,
id: editorObj.svgCanvas.getNextId(),
style: 'pointer-events:inherit'
}
});
editorObj.svgCanvas.setHref(newImage, result);
editorObj.svgCanvas.selectOnly([ newImage ]);
editorObj.svgCanvas.alignSelectedElements('m', 'page');
editorObj.svgCanvas.alignSelectedElements('c', 'page');
editorObj.topPanel.updateContextPanel();
$id('se-prompt-dialog').setAttribute('close', true);
};
// create dummy img so we know the default dimensions
let imgWidth = 100;
let imgHeight = 100;
const img = new Image();
img.style.opacity = 0;
img.addEventListener('load', () => {
imgWidth = img.offsetWidth || img.naturalWidth || img.width;
imgHeight = img.offsetHeight || img.naturalHeight || img.height;
insertNewImage(imgWidth, imgHeight);
});
img.src = result;
};
reader.readAsDataURL(file);
}
};
this.workarea.addEventListener('dragenter', this.onDragEnter);
this.workarea.addEventListener('dragover', this.onDragOver);
this.workarea.addEventListener('dragleave', this.onDragLeave);
this.workarea.addEventListener('drop', importImage);
const imgImport = document.createElement('input');
imgImport.type="file";
imgImport.addEventListener('change', importImage);
window.addEventListener('importImages', () => imgImport.click());
}
this.updateCanvas(true);
// Load extensions
this.extAndLocaleFunc();
// Defer injection to wait out initial menu processing. This probably goes
// away once all context menu behavior is brought to context menu.
this.ready(() => {
injectExtendedContextMenuItemsIntoDom();
});
// run callbacks stored by this.ready
await this.runCallbacks();
window.addEventListener('message', this.messageListener.bind(this));
}
/**
* @fires module:svgcanvas.SvgCanvas#event:ext_addLangData
* @fires module:svgcanvas.SvgCanvas#event:ext_langReady
* @fires module:svgcanvas.SvgCanvas#event:ext_langChanged
* @fires module:svgcanvas.SvgCanvas#event:extensions_added
* @returns {Promise<module:locale.LangAndData>} Resolves to result of {@link module:locale.readLang}
*/
async extAndLocaleFunc () {
this.$svgEditor.style.visibility = 'visible';
try {
// load standard extensions
await Promise.all(
this.configObj.curConfig.extensions.map(async (extname) => {
/**
* @tutorial ExtensionDocs
* @typedef {PlainObject} module:SVGthis.ExtensionObject
* @property {string} [name] Name of the extension. Used internally; no need for i18n. Defaults to extension name without beginning "ext-" or ending ".js".
* @property {module:svgcanvas.ExtensionInitCallback} [init]
*/
try {
/**
* @type {module:SVGthis.ExtensionObject}
*/
// eslint-disable-next-line no-unsanitized/method
const imported = await import(`./extensions/${encodeURIComponent(extname)}/${encodeURIComponent(extname)}.js`);
const { name = extname, init: initfn } = imported.default;
return this.addExtension(name, (initfn && initfn.bind(this)), { langParam: 'en' }); /** @todo change to current lng */
} catch (err) {
// Todo: Add config to alert any errors
console.error('Extension failed to load: ' + extname + '; ', err);
return undefined;
}
})
);
// load user extensions (given as pathNames)
await Promise.all(
this.configObj.curConfig.userExtensions.map(async (extPathName) => {
/**
* @tutorial ExtensionDocs
* @typedef {PlainObject} module:SVGthis.ExtensionObject
* @property {string} [name] Name of the extension. Used internally; no need for i18n. Defaults to extension name without beginning "ext-" or ending ".js".
* @property {module:svgcanvas.ExtensionInitCallback} [init]
*/
try {
/**
* @type {module:SVGthis.ExtensionObject}
*/
// eslint-disable-next-line no-unsanitized/method
const imported = await import(encodeURI(extPathName));
const { name, init: initfn } = imported.default;
return this.addExtension(name, (initfn && initfn.bind(this)), {});
} catch (err) {
// Todo: Add config to alert any errors
console.error('Extension failed to load: ' + extPathName + '; ', err);
return undefined;
}
})
);
this.svgCanvas.bind(
'extensions_added',
/**
* @param {external:Window} _win
* @param {module:svgcanvas.SvgCanvas#event:extensions_added} _data
* @listens module:SvgCanvas#event:extensions_added
* @returns {void}
*/
(_win, _data) => {
this.extensionsAdded = true;
this.setAll();
if (this.storagePromptState === 'ignore') {
this.updateCanvas(true);
}
this.messageQueue.forEach(
/**
* @param {module:svgcanvas.SvgCanvas#event:message} messageObj
* @fires module:svgcanvas.SvgCanvas#event:message
* @returns {void}
*/
(messageObj) => {
this.svgCanvas.call('message', messageObj);
}
);
}
);
this.svgCanvas.call('extensions_added');
} catch (err) {
// Todo: Report errors through the UI
console.error(err);
}
}
/**
* @param {PlainObject} info
* @param {any} info.data
* @param {string} info.origin
* @fires module:svgcanvas.SvgCanvas#event:message
* @returns {void}
*/
messageListener ({ data, origin }) {
const messageObj = { data, origin };
if (!this.extensionsAdded) {
this.messageQueue.push(messageObj);
} else {
// Extensions can handle messages at this stage with their own
// canvas `message` listeners
this.svgCanvas.call('message', messageObj);
}
}
}
export default EditorStartup;
</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>