Merge pull request #632 from SVG-Edit/issues/631

master
JFH 2021-09-22 16:01:30 +02:00 committed by GitHub
commit 552d4cb57b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 519 additions and 401 deletions

View File

@ -277,25 +277,21 @@ class MainMenu {
init() {
// add Top panel
const template = document.createElement("template");
const { i18next } = this.editor;
const { imgPath } = this.editor.configObj.curConfig;
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
<se-menu id="main_button" label="SVG-Edit" src="${imgPath}/logo.svg" alt="logo">
<se-menu-item id="tool_import" label="${i18next.t('tools.import_doc')}" src="${imgPath}/importImg.svg"></se-menu-item>
<se-menu-item id="tool_export" label="${i18next.t('tools.export_img')}" src="${imgPath}/export.svg"></se-menu-item>
<se-menu-item id="tool_docprops" label="${i18next.t('tools.docprops')}" shortcut="D" src="${imgPath}/docprop.svg"></se-menu-item>
<se-menu-item id="tool_editor_prefs" label="${i18next.t('config.editor_prefs')}" src="${imgPath}/editPref.svg"></se-menu-item>
<se-menu-item id="tool_editor_homepage" label="${i18next.t('tools.editor_homepage')}" src="${imgPath}/logo.svg"></se-menu-item>
</se-menu>
`;
<se-menu id="main_button" label="SVG-Edit" src="logo.svg" alt="logo">
<se-menu-item id="tool_import" label="tools.import_doc" src="importImg.svg"></se-menu-item>
<se-menu-item id="tool_export" label="tools.export_img" src="export.svg"></se-menu-item>
<se-menu-item id="tool_docprops" label="tools.docprops" shortcut="D" src="docprop.svg"></se-menu-item>
<se-menu-item id="tool_editor_prefs" label="config.editor_prefs" src="editPref.svg"></se-menu-item>
<se-menu-item id="tool_editor_homepage" label="tools.editor_homepage" src="logo.svg"></se-menu-item>
</se-menu>`;
this.editor.$svgEditor.append(template.content.cloneNode(true));
// register action to main menu entries
/**
* Associate all button actions as well as non-button keyboard shortcuts.
*/
$id("tool_import").addEventListener("click", () => {
this.clickImport();
window.dispatchEvent(new CustomEvent("importImages"));

View File

@ -10,5 +10,6 @@ import './seMenuItem.js';
import './seList.js';
import './seListItem.js';
import './seColorPicker.js';
import './seSelect';
import './seSelect.js';
import './seText.js';

View File

@ -1,3 +1,5 @@
/* globals svgEditor */
import { t } from '../locale.js';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
@ -54,6 +56,7 @@ export class ToolButton extends HTMLElement {
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$img = this._shadowRoot.querySelector('img');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
@ -75,14 +78,18 @@ export class ToolButton extends HTMLElement {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$div.setAttribute('title', `${newValue} ${shortcut ? `[${shortcut}]` : ''}`);
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'style':
this.$div.style = newValue;
break;
case 'src':
if (newValue.indexOf("data:") !== -1) {
this.$img.setAttribute('src', newValue);
} else {
this.$img.setAttribute('src', this.imgPath + "/" + newValue);
}
break;
case 'pressed':
if (newValue === null) {

View File

@ -1,6 +1,8 @@
/* globals svgEditor */
/* eslint-disable max-len */
import { jGraduate, jGraduateMethod } from './jgraduate/jQuery.jGraduate.js';
import PaintBox from './PaintBox.js';
import { t } from '../locale.js';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
@ -665,6 +667,7 @@ export class SeColorPicker extends HTMLElement {
this.i18next = null;
this.$picker = this._shadowRoot.getElementById('picker');
this.$color_picker = this._shadowRoot.getElementById('color_picker');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function init
@ -673,7 +676,7 @@ export class SeColorPicker extends HTMLElement {
*/
init (i18next) {
this.i18next = i18next;
this.setAttribute('config-change_xxx_color', i18next.t('config.change_xxx_color'));
this.setAttribute('config-change_xxx_color', t('config.change_xxx_color'));
}
/**
* @function observedAttributes
@ -693,10 +696,10 @@ export class SeColorPicker extends HTMLElement {
if (oldValue === newValue) return;
switch (name) {
case 'src':
this.$logo.setAttribute('src', newValue);
this.$logo.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'label':
this.setAttribute('title', newValue);
this.setAttribute('title', t(newValue));
break;
case 'type':
this.$label.setAttribute('title', 'config.pick_paint_opavity');

View File

@ -1,3 +1,4 @@
/* globals svgEditor */
/* eslint-disable no-unsanitized/property */
const template = document.createElement('template');
template.innerHTML = `
@ -119,6 +120,7 @@ export class ExplorerButton extends HTMLElement {
this.$lib = this._shadowRoot.querySelector('.image-lib');
this.files = [];
this.request = new XMLHttpRequest();
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
@ -172,7 +174,7 @@ export class ExplorerButton extends HTMLElement {
}
break;
case 'src':
this.$img.setAttribute('src', newValue);
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
default:
// eslint-disable-next-line no-console

View File

@ -1,3 +1,5 @@
/* globals svgEditor */
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
<style>
@ -99,6 +101,7 @@ export class FlyingButton extends HTMLElement {
// the last element of the div is the slot
// we retrieve all elements added in the slot (i.e. se-buttons)
this.$elements = this.$menu.lastElementChild.assignedElements();
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
@ -120,7 +123,7 @@ export class FlyingButton extends HTMLElement {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$button.setAttribute('title', `${newValue} [${shortcut}]`);
this.$button.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'pressed':
@ -232,9 +235,8 @@ export class FlyingButton extends HTMLElement {
* @returns {void}
*/
connectedCallback () {
// initialize currentAction with the first slot of the list
this.activeSlot = this.shadowRoot.querySelector('slot').assignedElements()[0];
this.$img.setAttribute('src', this.activeSlot.getAttribute('src'));
this.$img.setAttribute('src', this.imgPath + '/' + this.activeSlot.getAttribute('src'));
// capture click event on the button to manage the logic
const onClickHandler = (ev) => {
ev.stopPropagation();
@ -250,7 +252,7 @@ export class FlyingButton extends HTMLElement {
break;
case 'SE-BUTTON':
// change to the current action
this.$img.setAttribute('src', ev.target.getAttribute('src'));
this.$img.setAttribute('src', this.imgPath + '/' + ev.target.getAttribute('src'));
this.activeSlot = ev.target;
this.setAttribute('pressed', 'pressed');
// and close the menu

View File

@ -1,4 +1,5 @@
import 'elix/define/Input.js';
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
@ -46,6 +47,7 @@ export class SEInput extends HTMLElement {
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
// locate the component
this.$div = this._shadowRoot.querySelector('div');
this.$img = this._shadowRoot.querySelector('img');
this.$label = this.shadowRoot.getElementById('label');
this.$event = new CustomEvent('change');
@ -56,7 +58,7 @@ export class SEInput extends HTMLElement {
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'value', 'label', 'src', 'size' ];
return [ 'value', 'label', 'src', 'size', 'title' ];
}
/**
* @function attributeChangedCallback
@ -68,6 +70,9 @@ export class SEInput extends HTMLElement {
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
switch (name) {
case 'title':
this.$div.setAttribute('title', `${t(newValue)}`);
break;
case 'src':
this.$img.setAttribute('src', newValue);
this.$label.remove();
@ -76,7 +81,7 @@ export class SEInput extends HTMLElement {
this.$input.setAttribute('size', newValue);
break;
case 'label':
this.$label.textContent = newValue;
this.$label.textContent = t(newValue);
this.$img.remove();
break;
case 'value':
@ -88,6 +93,21 @@ export class SEInput extends HTMLElement {
break;
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
}
/**
* @function set
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
}
/**
* @function get
* @returns {any}

View File

@ -1,4 +1,6 @@
/* globals svgEditor */
import 'elix/define/DropdownList.js';
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
@ -43,13 +45,16 @@ export class SeList extends HTMLElement {
this._shadowRoot.append(template.content.cloneNode(true));
this.$dropdown = this._shadowRoot.querySelector('elix-dropdown-list');
this.$label = this._shadowRoot.querySelector('label');
this.$selction = this.$dropdown.shadowRoot.querySelector('#source').querySelector('#value');
this.items = this.querySelectorAll("se-list-item");
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'label', 'width', 'height' ];
return [ 'label', 'width', 'height', 'title', 'value' ];
}
/**
@ -60,10 +65,14 @@ export class SeList extends HTMLElement {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
const currentObj = this;
if (oldValue === newValue) return;
switch (name) {
case 'title':
this.$dropdown.setAttribute('title', `${t(newValue)}`);
break;
case 'label':
this.$label.textContent = newValue;
this.$label.textContent = t(newValue);
break;
case 'height':
this.$dropdown.style.height = newValue;
@ -71,12 +80,44 @@ export class SeList extends HTMLElement {
case 'width':
this.$dropdown.style.width = newValue;
break;
case 'value':
Array.from(this.items).forEach(function (element) {
if(element.getAttribute("value") === newValue) {
if (element.hasAttribute("src")) {
while(currentObj.$selction.firstChild)
currentObj.$selction.removeChild(currentObj.$selction.firstChild);
const img = document.createElement('img');
img.src = currentObj.imgPath + '/' + element.getAttribute("src");
img.style.height = element.getAttribute("img-height");
img.setAttribute('title', t(element.getAttribute("title")));
currentObj.$selction.append(img);
} else {
currentObj.$selction.textContent = t(element.getAttribute('option'));
}
}
});
break;
default:
// eslint-disable-next-line no-console
console.error(`unknown attribute: ${name}`);
break;
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
}
/**
* @function set
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
}
/**
* @function get
* @returns {any}
@ -134,6 +175,7 @@ export class SeList extends HTMLElement {
const closeEvent = new CustomEvent('change', { detail: { value } });
currentObj.dispatchEvent(closeEvent);
currentObj.value = value;
currentObj.setAttribute("value", value);
}
});
this.$dropdown.addEventListener('close', (_e) => {

View File

@ -1,4 +1,6 @@
/* globals svgEditor */
import 'elix/define/Option.js';
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
@ -12,6 +14,7 @@ template.innerHTML = `
}
</style>
<elix-option aria-label="option">
<img alt="icon" />
<slot></slot>
</elix-option>
`;
@ -30,13 +33,16 @@ export class SeListItem extends HTMLElement {
this.$menuitem = this._shadowRoot.querySelector('elix-option');
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark');
this.$svg.setAttribute('style', 'display: none;');
this.$img = this._shadowRoot.querySelector('img');
this.$img.setAttribute('style', 'display: none;');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'option' ];
return [ 'option', 'src', 'title', 'img-height' ];
}
/**
@ -51,6 +57,17 @@ export class SeListItem extends HTMLElement {
switch (name) {
case 'option':
this.$menuitem.setAttribute('option', newValue);
this.$menuitem.textContent = t(newValue);
break;
case 'src':
this.$img.setAttribute('style', 'display: block;');
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'title':
this.$img.setAttribute('title', t(newValue));
break;
case 'img-height':
this.$img.setAttribute('height', newValue);
break;
default:
// eslint-disable-next-line no-console
@ -73,6 +90,51 @@ export class SeListItem extends HTMLElement {
set option (value) {
this.setAttribute('option', value);
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
}
/**
* @function set
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
}
/**
* @function get
* @returns {any}
*/
get imgHeight () {
return this.getAttribute('img-height');
}
/**
* @function set
* @returns {void}
*/
set imgHeight (value) {
this.setAttribute('img-height', value);
}
/**
* @function get
* @returns {any}
*/
get src () {
return this.getAttribute('src');
}
/**
* @function set
* @returns {void}
*/
set src (value) {
this.setAttribute('src', value);
}
}
// Register

View File

@ -1,3 +1,4 @@
/* globals svgEditor */
import 'elix/define/MenuItem.js';
import './sePlainMenuButton.js';
@ -43,6 +44,7 @@ export class SeMenu extends HTMLElement {
this._shadowRoot.append(template.content.cloneNode(true));
this.$menu = this._shadowRoot.querySelector('elix-menu-button');
this.$label = this.$menu.shadowRoot.querySelector('#popupToggle').shadowRoot;
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
@ -64,7 +66,7 @@ export class SeMenu extends HTMLElement {
if (oldValue === newValue) return;
switch (name) {
case 'src':
image.src = newValue;
image.src = this.imgPath + '/' + newValue;
image.width = 24;
image.height = 24;
this.$label.prepend(image);

View File

@ -1,6 +1,7 @@
/* globals svgEditor */
import 'elix/define/Menu.js';
import 'elix/define/MenuItem.js';
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
<style>
@ -29,6 +30,7 @@ export class SeMenuItem extends HTMLElement {
this.$menuitem = this._shadowRoot.querySelector('elix-menu-item');
this.$svg = this.$menuitem.shadowRoot.querySelector('#checkmark');
this.$svg.setAttribute('style', 'display: none;');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
@ -49,12 +51,12 @@ export class SeMenuItem extends HTMLElement {
if (oldValue === newValue) return;
switch (name) {
case 'src':
this.$img.setAttribute('src', newValue);
this.$img.style.display = 'inline-block';
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
break;
case 'label':
shortcut = this.getAttribute('shortcut');
this.$label.textContent = `${newValue} ${shortcut ? `(${shortcut})` : ''}`;
this.$label.textContent = `${t(newValue)} ${shortcut ? `(${shortcut})` : ''}`;
break;
default:
// eslint-disable-next-line no-console

View File

@ -1,4 +1,6 @@
/* globals svgEditor */
import '../dialogs/se-elix/define/NumberSpinBox.js';
import { t } from '../locale.js';
const template = document.createElement('template');
template.innerHTML = `
@ -67,13 +69,14 @@ export class SESpinInput extends HTMLElement {
this.$label = this.shadowRoot.getElementById('label');
this.$event = new CustomEvent('change');
this.$input = this._shadowRoot.querySelector('elix-number-spin-box');
this.imgPath = svgEditor.configObj.curConfig.imgPath;
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'value', 'label', 'src', 'size', 'min', 'max', 'step' ];
return [ 'value', 'label', 'src', 'size', 'min', 'max', 'step', 'title' ];
}
/**
* @function attributeChangedCallback
@ -85,8 +88,14 @@ export class SESpinInput extends HTMLElement {
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
switch (name) {
case 'title':
{
const shortcut = this.getAttribute('shortcut');
this.$div.setAttribute('title', `${t(newValue)} ${shortcut ? `[${t(shortcut)}]` : ''}`);
}
break;
case 'src':
this.$img.setAttribute('src', newValue);
this.$img.setAttribute('src', this.imgPath + '/' + newValue);
this.$label.remove();
this.$div.classList.add('imginside');
break;
@ -106,7 +115,7 @@ export class SESpinInput extends HTMLElement {
this.$input.setAttribute('max', newValue);
break;
case 'label':
this.$label.textContent = newValue;
this.$label.textContent = t(newValue);
this.$img.remove();
break;
case 'value':
@ -118,6 +127,21 @@ export class SESpinInput extends HTMLElement {
break;
}
}
/**
* @function get
* @returns {any}
*/
get title () {
return this.getAttribute('title');
}
/**
* @function set
* @returns {void}
*/
set title (value) {
this.setAttribute('title', value);
}
/**
* @function get
* @returns {any}

View File

@ -0,0 +1,97 @@
import { t } from '../locale.js';
const template = document.createElement('template');
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
<style>
</style>
<div></div>
`;
/**
* @class SeText
*/
export class SeText extends HTMLElement {
/**
* @function constructor
*/
constructor () {
super();
// create the shadowDom and insert the template
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.append(template.content.cloneNode(true));
// locate the component
this.$div = this._shadowRoot.querySelector('div');
}
/**
* @function observedAttributes
* @returns {any} observed
*/
static get observedAttributes () {
return [ 'text', 'value', 'style' ];
}
/**
* @function attributeChangedCallback
* @param {string} name
* @param {string} oldValue
* @param {string} newValue
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
switch (name) {
case 'text':
this.$div.setAttribute('title', t(newValue));
break;
case 'style':
this.$div.style = newValue;
break;
case 'value':
this.$div.value = newValue;
break;
default:
// eslint-disable-next-line no-console
console.error(`unknown attribute: ${name}`);
break;
}
}
/**
* @function get
* @returns {any}
*/
get text () {
return this.getAttribute('text');
}
/**
* @function set
* @returns {void}
*/
set text (value) {
this.setAttribute('text', value);
}
/**
* @function get
* @returns {any}
*/
get value () {
return this.value;
}
/**
* @function set
* @returns {void}
*/
set value (value) {
this.value = value;
}
/**
* @function connectedCallback
* @returns {void}
*/
connectedCallback () {
// capture shortcuts
}
}
// Register
customElements.define('se-text', SeText);

View File

@ -1,3 +1,4 @@
/* globals svgEditor */
import ListComboBox from 'elix/define/ListComboBox.js';
import * as internal from 'elix/src/base/internal.js';
import { templateFrom, fragmentFrom } from 'elix/src/core/htmlLiterals.js';
@ -74,13 +75,16 @@ class Zoom extends ListComboBox {
* @returns {void}
*/
attributeChangedCallback (name, oldValue, newValue) {
if (oldValue === newValue) return;
if (oldValue === newValue && name !== "src") return;
switch (name) {
case 'title':
// this.$span.setAttribute('title', `${newValue} ${shortcut ? `[${shortcut}]` : ''}`);
break;
case 'src':
this.src = newValue;
{
const { imgPath } = svgEditor.configObj.curConfig;
this.src = imgPath + '/' + newValue;
}
break;
case 'inputsize':
this.inputsize = newValue;

View File

@ -182,7 +182,7 @@ export class SeCMenuLayerDialog extends HTMLElement {
const onMenuOpenHandler = (e) => {
e.preventDefault();
current.$dialog.style.top = e.pageY + 'px';
current.$dialog.style.left = e.pageX + 'px';
current.$dialog.style.left = e.pageX - 126 + 'px';
current.$dialog.style.display = 'block';
};
const onMenuCloseHandler = (e) => {

View File

@ -31,7 +31,6 @@ export default {
const { svgCanvas } = svgEditor;
const { getElem, $id, mergeDeep } = svgCanvas;
const { svgroot } = S;
const { imgPath } = svgEditor.configObj.curConfig;
const addElem = svgCanvas.addSVGElementFromJson;
const selManager = S.selectorManager;
await loadExtensionTranslation(svgEditor);
@ -354,10 +353,10 @@ export default {
return {
name: svgEditor.i18next.t(`${name}:name`),
callback() {
const btitle = svgEditor.i18next.t(`${name}:langListTitle`);
const btitle = `${name}:langListTitle`;
// eslint-disable-next-line no-unsanitized/property
const buttonTemplate = `
<se-button id="mode_connect" title="${btitle}" src="${imgPath}/conn.svg"></se-button>
<se-button id="mode_connect" title="${btitle}" src="conn.svg"></se-button>
`;
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 13);
$id('mode_connect').addEventListener("click", () => {

View File

@ -29,7 +29,6 @@ export default {
name,
async init(S) {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
await loadExtensionTranslation(svgEditor);
const { ChangeElementCommand } = S; // , svgcontent,
// svgdoc = S.svgroot.parentNode.ownerDocument,
@ -83,11 +82,11 @@ export default {
name: svgEditor.i18next.t(`${name}:name`),
callback() {
// Add the button and its handler(s)
const title = svgEditor.i18next.t(`${name}:buttons.0.title`);
const key = svgEditor.i18next.t(`${name}:buttons.0.key`);
const title = `${name}:buttons.0.title`;
const key = `${name}:buttons.0.key`;
// eslint-disable-next-line no-unsanitized/property
const buttonTemplate = `
<se-button id="tool_eyedropper" title="${title}" src="${imgPath}/eye_dropper.svg" shortcut=${key}></se-button>
<se-button id="tool_eyedropper" title="${title}" src="eye_dropper.svg" shortcut=${key}></se-button>
`;
svgCanvas.insertChildAtIndex($id('tools_left'), buttonTemplate, 12);
$id('tool_eyedropper').addEventListener("click", () => {

View File

@ -28,7 +28,6 @@ export default {
name,
async init ({ NS, getTypeMap }) {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
await loadExtensionTranslation(svgEditor);
const { svgCanvas } = svgEditor;
const { $id } = svgCanvas;
@ -164,11 +163,11 @@ export default {
callback () {
// Add the button and its handler(s)
const buttonTemplate = document.createElement("template");
const title = svgEditor.i18next.t(`${name}:buttons.0.title`);
const title = `${name}:buttons.0.title`;
// eslint-disable-next-line no-unsanitized/property
buttonTemplate.innerHTML = `
<se-button id="view_grid" title="${title}" src="${imgPath}/grid.svg"></se-button>
<se-button id="view_grid" title="${title}" src="grid.svg"></se-button>
`;
$id('editor_panel').append(buttonTemplate.content.cloneNode(true));
$id('view_grid').addEventListener("click", () => {

View File

@ -34,7 +34,6 @@ export default {
name,
async init ({ _importLocale }) {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
await loadExtensionTranslation(svgEditor);
const { svgCanvas } = svgEditor;
const { $id } = svgCanvas;
@ -43,10 +42,10 @@ export default {
callback() {
// Add the button and its handler(s)
const buttonTemplate = document.createElement("template");
const title = svgEditor.i18next.t(`${name}:buttons.0.title`);
const title = `${name}:buttons.0.title`;
// eslint-disable-next-line no-unsanitized/property
buttonTemplate.innerHTML = `
<se-button id="hello_world" title="${title}" src="${imgPath}/hello_world.svg"></se-button>
<se-button id="hello_world" title="${title}" src="hello_world.svg"></se-button>
`;
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
$id('hello_world').addEventListener("click", () => {

View File

@ -522,8 +522,9 @@ export default {
callback() {
// Add the button and its handler(s)
const buttonTemplate = document.createElement("template");
const key = name + `:buttons.0.title`;
buttonTemplate.innerHTML = `
<se-menu-item id="tool_imagelib" label="Image library" src="${imgPath}/library.svg"></se-menu-item>
<se-menu-item id="tool_imagelib" label="${key}" src="library.svg"></se-menu-item>
`;
insertAfter($id('tool_export'), buttonTemplate.content.cloneNode(true));
$id('tool_imagelib').addEventListener("click", () => {

View File

@ -39,7 +39,6 @@ export default {
name,
async init(_S) {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
const { svgCanvas } = svgEditor;
const { $id } = svgCanvas;
await loadExtensionTranslation(svgEditor);
@ -162,13 +161,13 @@ export default {
callback() {
// eslint-disable-next-line no-unsanitized/property
const buttonTemplate = `
<se-menu-item id="tool_clear" label="${svgEditor.i18next.t('opensave.new_doc')}" shortcut="N" src="${imgPath}/new.svg"></se-menu-item>`;
<se-menu-item id="tool_clear" label="opensave.new_doc" shortcut="N" src="new.svg"></se-menu-item>`;
svgCanvas.insertChildAtIndex($id('main_button'), buttonTemplate, 0);
const openButtonTemplate = `<se-menu-item id="tool_open" label="${svgEditor.i18next.t('opensave.open_image_doc')}" src="${imgPath}/open.svg"></se-menu-item>`;
const openButtonTemplate = `<se-menu-item id="tool_open" label="opensave.open_image_doc" src="open.svg"></se-menu-item>`;
svgCanvas.insertChildAtIndex($id('main_button'), openButtonTemplate, 1);
const saveButtonTemplate = `<se-menu-item id="tool_save" label="${svgEditor.i18next.t('opensave.save_doc')}" shortcut="S" src="${imgPath}/saveImg.svg"></se-menu-item>`;
const saveButtonTemplate = `<se-menu-item id="tool_save" label="opensave.save_doc" shortcut="S" src="saveImg.svg"></se-menu-item>`;
svgCanvas.insertChildAtIndex($id('main_button'), saveButtonTemplate, 2);
const saveAsButtonTemplate = `<se-menu-item id="tool_save_as" label="${svgEditor.i18next.t('opensave.save_as_doc')}" src="${imgPath}/saveImg.svg"></se-menu-item>`;
const saveAsButtonTemplate = `<se-menu-item id="tool_save_as" label="opensave.save_as_doc" src="saveImg.svg"></se-menu-item>`;
svgCanvas.insertChildAtIndex($id('main_button'), saveAsButtonTemplate, 3);
// handler
$id("tool_clear").addEventListener("click", clickClear.bind(this));

View File

@ -31,8 +31,6 @@ export default {
name,
async init() {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
await loadExtensionTranslation(svgEditor);
const {
svgCanvas
@ -46,12 +44,12 @@ export default {
return {
name: svgEditor.i18next.t(`${name}:name`),
callback() {
const btitle = svgEditor.i18next.t(`${name}:buttons.0.title`);
const btitle = `${name}:buttons.0.title`;
// Add the button and its handler(s)
const buttonTemplate = document.createElement("template");
// eslint-disable-next-line no-unsanitized/property
buttonTemplate.innerHTML = `
<se-button id="ext-panning" title="${btitle}" src="${imgPath}/panning.svg"></se-button>
<se-button id="ext-panning" title="${btitle}" src="panning.svg"></se-button>
`;
insertAfter($id('tool_zoom'), buttonTemplate.content.cloneNode(true));
$id('ext-panning').addEventListener("click", () => {

View File

@ -29,7 +29,6 @@ export default {
name,
async init(_S) {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
const { ChangeElementCommand } = _S; // , svgcontent,
const addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); };
const { svgCanvas } = svgEditor;
@ -81,15 +80,15 @@ export default {
callback() {
// Add the button and its handler(s)
// Note: the star extension needs to be loaded before the polygon extension
const fbtitle = svgEditor.i18next.t(`${name}:title`);
const title_star = svgEditor.i18next.t(`${name}:buttons.0.title`);
const title_polygon = svgEditor.i18next.t(`${name}:buttons.1.title`);
const fbtitle = `${name}:title`;
const title_star = `${name}:buttons.0.title`;
const title_polygon = `${name}:buttons.1.title`;
// eslint-disable-next-line no-unsanitized/property
const buttonTemplate = `
<se-flyingbutton id="tools_polygon" title="${fbtitle}">
<se-button id="tool_star" title="${title_star}" src="${imgPath}/star.svg">
<se-button id="tool_star" title="${title_star}" src="star.svg">
</se-button>
<se-button id="tool_polygon" title="${title_polygon}" src="${imgPath}/polygon.svg">
<se-button id="tool_polygon" title="${title_polygon}" src="polygon.svg">
</se-button>
</se-flyingbutton>
`;
@ -109,15 +108,14 @@ export default {
showPanel(false, "star");
}
});
const label0 = svgEditor.i18next.t(`${name}:contextTools.0.label`);
const title0 = svgEditor.i18next.t(`${name}:contextTools.0.title`);
const label1 = svgEditor.i18next.t(`${name}:contextTools.1.label`);
const title1 = svgEditor.i18next.t(`${name}:contextTools.1.title`);
const label2 = svgEditor.i18next.t(`${name}:contextTools.2.label`);
const title2 = svgEditor.i18next.t(`${name}:contextTools.2.title`);
const label3 = svgEditor.i18next.t(`${name}:contextTools.3.label`);
const title3 = svgEditor.i18next.t(`${name}:contextTools.3.title`);
const label0 = `${name}:contextTools.0.label`;
const title0 = `${name}:contextTools.0.title`;
const label1 = `${name}:contextTools.1.label`;
const title1 = `${name}:contextTools.1.title`;
const label2 = `${name}:contextTools.2.label`;
const title2 = `${name}:contextTools.2.title`;
const label3 = `${name}:contextTools.3.label`;
const title3 = `${name}:contextTools.3.title`;
// Add the context panel and its handler(s)
const panelTemplate = document.createElement("template");
// eslint-disable-next-line no-unsanitized/property

View File

@ -27,7 +27,6 @@ export default {
name,
async init () {
const svgEditor = this;
const { imgPath } = svgEditor.configObj.curConfig;
const canv = svgEditor.svgCanvas;
const { $id } = canv;
const svgroot = canv.getRootElem();
@ -47,7 +46,7 @@ export default {
// eslint-disable-next-line no-unsanitized/property
const buttonTemplate = `
<se-explorerbutton id="tool_shapelib" title="${svgEditor.i18next.t(`${name}:buttons.0.title`)}" lib="./extensions/ext-shapes/shapelib/"
src="${imgPath}/shapelib.svg"></se-explorerbutton>
src="shapelib.svg"></se-explorerbutton>
`;
canv.insertChildAtIndex($id('tools_left'), buttonTemplate, 9);
$id('tool_shapelib').addEventListener("click", () => {

View File

@ -86,3 +86,7 @@ export const putLocale = async function (givenParam, goodLangs) {
console.info(`Lang: ${i18next.t('lang')}`);
return { langParam, i18next };
};
export const t = function (key) {
return i18next.t(key);
};

View File

@ -70,13 +70,30 @@ export default {
straight_segments: 'Straight',
curve_segments: 'Curve',
text_contents: 'Change text contents',
font_family_label: 'Font',
font_family: 'Change Font Family',
font_size: 'Change Font Size',
bold: 'Bold Text [B]',
italic: 'Italic Text [I]',
bold: 'Bold Text',
italic: 'Italic Text',
text_anchor_start: 'Align the text in start',
text_anchor_middle: 'Align the text in middle',
text_anchor_end: 'Align the text in end',
r_label: 'r',
x_label: 'x',
y_label: 'y',
x1_label: 'x1',
y1_label: 'y1',
x2_label: 'x2',
y2_label: 'y2',
rx_label: 'rx',
ry_label: 'ry',
cx_label: 'cx',
cy_label: 'cy',
w_label: 'w',
h_label: 'h',
id_label: 'id',
class_label: 'class',
label: 'label',
class: 'Element class',
serif: 'Serif',
sans_serif: 'Sans-serif',
@ -129,21 +146,21 @@ export default {
mode_path: 'Path Tool',
mode_text: 'Text Tool',
mode_image: 'Image Tool',
mode_zoom: 'Zoom Tool [Ctrl+Up/Down]',
mode_zoom: 'Zoom Tool',
no_embed: 'NOTE: This image cannot be embedded. It will depend on this path to be displayed',
undo: 'Undo [Z]',
redo: 'Redo [Y]',
undo: 'Undo',
redo: 'Redo',
tool_source: 'Edit Source',
wireframe_mode: 'Wireframe Mode',
clone: 'Duplicate Element(s) [D]',
clone: 'Duplicate Element(s)',
del: 'Delete Element(s)',
group_elements: 'Group Elements [G]',
group_elements: 'Group Elements',
make_link: 'Make (hyper)link',
set_link_url: 'Set link URL (leave empty to remove)',
to_path: 'Convert to Path',
reorient_path: 'Reorient path',
ungroup: 'Ungroup Elements',
docprops: 'Document Properties [D]',
docprops: 'Document Properties',
editor_homepage: 'SVG-Edit Home Page',
move_bottom: 'Send to Back',
move_top: 'Bring to Front',

View File

@ -164,50 +164,41 @@ class BottomPanel {
// register actions for Bottom panel
const template = document.createElement('template');
const { i18next } = this.editor;
const { imgPath } = this.editor.configObj.curConfig;
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
<div id="tools_bottom">
<!-- Zoom buttons -->
<se-zoom id="zoom" src="${imgPath}/zoom.svg" title="Change zoom level" inputsize="40px">
<div value="1000">1000</div>
<div value="400">400</div>
<div value="200">200</div>
<div value="100">100</div>
<div value="50">50</div>
<div value="25">25</div>
<div value="canvas">${i18next.t('tools.fit_to_canvas')}</div>
<div value="selection">${i18next.t('tools.fit_to_sel')}</div>
<div value="layer">${i18next.t('tools.fit_to_layer_content')}</div>
<div value="content">${i18next.t('tools.fit_to_all')}</div>
<se-zoom id="zoom" src="zoom.svg" title="Change zoom level" inputsize="40px">
<se-text value="1000" text="1000"></se-text>
<se-text value="400" text="400"></se-text>
<se-text value="200" text="200"></se-text>
<se-text value="100" text="100"></se-text>
<se-text value="50" text="50"></se-text>
<se-text value="25" text="25"></se-text>
<se-text value="canvas" text="tools.fit_to_canvas"></se-text>
<se-text value="selection" text="tools.fit_to_sel"></se-text>
<se-text value="layer" text="tools.fit_to_layer_content"></se-text>"
<se-text value="content" text="tools.fit_to_all"></se-text>
</se-zoom>
<se-colorpicker id="fill_color" src="${imgPath}/fill.svg" title="${i18next.t('properties.fill_color')}" type="fill"></se-colorpicker>
<se-colorpicker id="stroke_color" src="${imgPath}/stroke.svg" title="${i18next.t('properties.stroke_color')}" type="stroke">
</se-colorpicker>
<se-spin-input id="stroke_width" min=0 max=99 step=1 title="${i18next.t('properties.stroke_width')}" label=""></se-spin-input>
<se-colorpicker id="fill_color" src="fill.svg" label="properties.fill_color" type="fill"></se-colorpicker>
<se-colorpicker id="stroke_color" src="stroke.svg" label="properties.stroke_color" type="stroke"></se-colorpicker>
<se-spin-input id="stroke_width" min=0 max=99 step=1 title="properties.stroke_width" label=""></se-spin-input>
<se-select id="stroke_style" title="${i18next.t('properties.stroke_style')}" label="" width="22px" height="22px"
options="&#8212;,...,- -,- .,- .."
values="none 2,2 5,5 5,2,2,2 5,2,2,2,2,2">
</se-select>
<se-list id="stroke_linejoin" title="${i18next.t('properties.linejoin_miter')}" label="" width="22px" height="22px">
<se-list-item id="linejoin_miter" value="miter"><img title="${i18next.t('properties.linejoin_miter')}" src="${imgPath}/linejoin_miter.svg"
height="22px"></img></se-list-item>
<se-list-item id="linejoin_round" value="round"><img title="${i18next.t('properties.linejoin_round')}" src="${imgPath}/linejoin_round.svg"
height="22px"></img></se-list-item>
<se-list-item id="linejoin_bevel" value="bevel"><img title="${i18next.t('properties.linejoin_bevel')}" src="${imgPath}/linejoin_bevel.svg"
height="22px"></img></se-list-item>
<se-list id="stroke_linejoin" title="properties.linejoin_miter" label="" width="22px" height="22px">
<se-list-item id="linejoin_miter" value="miter" src="linejoin_miter.svg" title="properties.linejoin_miter" img-height="22px"></se-list-item>
<se-list-item id="linejoin_round" value="round" src="linejoin_round.svg" title="properties.linejoin_round" img-height="22px"></se-list-item>
<se-list-item id="linejoin_bevel" value="bevel" src="linejoin_bevel.svg" title="properties.linejoin_bevel" img-height="22px"></se-list-item>
</se-list>
<se-list id="stroke_linecap" title="${i18next.t('properties.linecap_butt')}" label="" width="22px" height="22px">
<se-list-item id="linecap_butt" value="butt"><img title="${i18next.t('properties.linecap_butt')}" src="${imgPath}/linecap_butt.svg"
height="22px"></img></se-list-item>
<se-list-item id="linecap_square" value="square"><img title="${i18next.t('properties.linecap_square')}" src="${imgPath}/linecap_square.svg"
height="22px"></img></se-list-item>
<se-list-item id="linecap_round" value="round"><img title="${i18next.t('properties.linecap_round')}" src="${imgPath}/linecap_round.svg"
height="22px"></img></se-list-item>
<se-list id="stroke_linecap" title="properties.linecap_butt" label="" width="22px" height="22px">
<se-list-item id="linecap_butt" value="butt" src="linecap_butt.svg" title="properties.linecap_butt" img-height="22px"></se-list-item>
<se-list-item id="linecap_square" value="square" src="linecap_square.svg" title="properties.linecap_square" img-height="22px"></se-list-item>
<se-list-item id="linecap_round" value="round" src="linecap_round.svg" title="properties.linecap_round" img-height="22px"></se-list-item>
</se-list>
<se-spin-input size="3" id="opacity" min=0 max=100 step=5 title="${i18next.t('properties.opacity')}"
src="${imgPath}/opacity.svg"></se-spin-input>
<se-spin-input size="3" id="opacity" min=0 max=100 step=5 title="properties.opacity" src="opacity.svg"></se-spin-input>
<se-palette id="palette"></se-palette>
</div>
`;

View File

@ -44,7 +44,6 @@ class LayersPanel {
init() {
const template = document.createElement("template");
const { i18next } = this.editor;
const { imgPath } = this.editor.configObj.curConfig;
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
@ -54,12 +53,12 @@ class LayersPanel {
<div id="layerpanel">
<h3 id="layersLabel">${i18next.t('layers.layers')}</h3>
<fieldset id="layerbuttons">
<se-button id="layer_new" title="${i18next.t('layers.new')}" size="small" src="${imgPath}/new.svg"></se-button>
<se-button id="layer_delete" title="${i18next.t('layers.del')}" size="small" src="${imgPath}/delete.svg"></se-button>
<se-button id="layer_rename" title="${i18next.t('layers.rename')}" size="small" src="${imgPath}/text.svg"></se-button>
<se-button id="layer_up" title="${i18next.t('layers.move_up')}" size="small" src="${imgPath}/go_up.svg"></se-button>
<se-button id="layer_down" title="${i18next.t('layers.move_down')}" size="small" src="${imgPath}/go_down.svg"></se-button>
<se-button id="layer_moreopts" title="${i18next.t('common.more_opts')}" size="small" src="${imgPath}/context_menu.svg">
<se-button id="layer_new" title="layers.new" size="small" src="new.svg"></se-button>
<se-button id="layer_delete" title="layers.del" size="small" src="delete.svg"></se-button>
<se-button id="layer_rename" title="layers.rename" size="small" src="text.svg"></se-button>
<se-button id="layer_up" title="layers.move_up" size="small" src="go_up.svg"></se-button>
<se-button id="layer_down" title="layers.move_down" size="small" src="go_down.svg"></se-button>
<se-button id="layer_moreopts" title="common.more_opts" size="small" src="context_menu.svg">
</se-button>
</fieldset>
<table id="layerlist">
@ -90,31 +89,14 @@ class LayersPanel {
menuLayerBox.setAttribute("leftclick", false);
this.editor.$container.append(menuLayerBox);
menuLayerBox.init(i18next);
document
.getElementById("layer_new")
.addEventListener("click", this.newLayer.bind(this));
document
.getElementById("layer_delete")
.addEventListener("click", this.deleteLayer.bind(this));
document
.getElementById("layer_up")
.addEventListener("click", () => this.moveLayer.bind(this)(-1));
document
.getElementById("layer_down")
.addEventListener("click", () => this.moveLayer.bind(this)(1));
document
.getElementById("layer_rename")
.addEventListener("click", this.layerRename.bind(this));
$id("se-cmenu-layers-more").addEventListener(
"change",
this.lmenuFunc.bind(this)
);
$id("se-cmenu-layers-list").addEventListener("change", (e) => {
this.lmenuFunc(e);
});
$id("sidepanel_handle").addEventListener(
"click", () => this.toggleSidePanel()
);
$id("layer_new").addEventListener("click", this.newLayer.bind(this));
$id("layer_delete").addEventListener("click", this.deleteLayer.bind(this));
$id("layer_up").addEventListener("click", () => this.moveLayer.bind(this)(-1));
$id("layer_down").addEventListener("click", () => this.moveLayer.bind(this)(1));
$id("layer_rename").addEventListener("click", this.layerRename.bind(this));
$id("se-cmenu-layers-more").addEventListener("change", this.lmenuFunc.bind(this));
$id("se-cmenu-layers-list").addEventListener("change", (e) => { this.lmenuFunc(e); });
$id("sidepanel_handle").addEventListener("click", () => this.toggleSidePanel());
this.toggleSidePanel(this.editor.configObj.curConfig.showlayers);
}
toggleSidePanel(displayFlag) {

View File

@ -195,53 +195,51 @@ class LeftPanel {
* @type {module}
*/
init() {
const { i18next } = this.editor;
const { imgPath } = this.editor.configObj.curConfig;
// add Left panel
const leftMenu = [
{
menu: `<se-button id="tool_select" title="${i18next.t('tools.mode_select')}" src="${imgPath}/select.svg"></se-button>`,
menu: `<se-button id="tool_select" title="tools.mode_select" src="select.svg"></se-button>`,
position: 1
},
{
menu: `<se-button id="tool_zoom" title="${i18next.t('tools.mode_zoom')}" src="${imgPath}/zoom.svg" shortcut="Z"></se-button>`,
menu: `<se-button id="tool_zoom" title="tools.mode_zoom" src="zoom.svg" shortcut="Z"></se-button>`,
position: 2
},
{
menu: `<se-button id="tool_fhpath" title="${i18next.t('tools.mode_fhpath')}" src="${imgPath}/pencil.svg" shortcut="Q"></se-button>`,
menu: `<se-button id="tool_fhpath" title="tools.mode_fhpath" src="pencil.svg" shortcut="Q"></se-button>`,
position: 3
},
{
menu: `<se-button id="tool_line" title="${i18next.t('tools.mode_line')}" src="${imgPath}/pen.svg" shortcut="L"></se-button>`,
menu: `<se-button id="tool_line" title="tools.mode_line" src="pen.svg" shortcut="L"></se-button>`,
position: 4
},
{
menu: `<se-button id="tool_path" title="${i18next.t('tools.mode_path')}" src="${imgPath}/path.svg" shortcut="P"></se-button>`,
menu: `<se-button id="tool_path" title="tools.mode_path" src="path.svg" shortcut="P"></se-button>`,
position: 5
},
{
menu: `<se-flyingbutton id="tools_rect" title="${i18next.t('tools.square_rect_tool')}">
<se-button id="tool_rect" title="${i18next.t('tools.mode_rect')}" src="${imgPath}/rect.svg" shortcut="R"></se-button>
<se-button id="tool_square" title="${i18next.t('tools.mode_square')}" src="${imgPath}/square.svg"></se-button>
<se-button id="tool_fhrect" title="${i18next.t('tools.mode_fhrect')}" src="${imgPath}/fh_rect.svg"></se-button>
menu: `<se-flyingbutton id="tools_rect" title="tools.square_rect_tool">
<se-button id="tool_rect" title="tools.mode_rect" src="rect.svg" shortcut="R"></se-button>
<se-button id="tool_square" title="tools.mode_square" src="square.svg"></se-button>
<se-button id="tool_fhrect" title="tools.mode_fhrect" src="fh_rect.svg"></se-button>
</se-flyingbutton>`,
position: 6
},
{
menu: `<se-flyingbutton id="tools_ellipse" title="${i18next.t('tools.ellipse_circle_tool')}">
<se-button id="tool_ellipse" title="${i18next.t('tools.mode_ellipse')}" src="${imgPath}/ellipse.svg" shortcut="E"></se-button>
<se-button id="tool_circle" title="${i18next.t('tools.mode_circle')}" src="${imgPath}/circle.svg"></se-button>
<se-button id="tool_fhellipse" title="${i18next.t('tools.mode_fhellipse')}" src="${imgPath}/fh_ellipse.svg"></se-button>
menu: `<se-flyingbutton id="tools_ellipse" title="tools.ellipse_circle_tool">
<se-button id="tool_ellipse" title="tools.mode_ellipse" src="ellipse.svg" shortcut="E"></se-button>
<se-button id="tool_circle" title="tools.mode_circle" src="circle.svg"></se-button>
<se-button id="tool_fhellipse" title="tools.mode_fhellipse" src="fh_ellipse.svg"></se-button>
</se-flyingbutton>`,
position: 7
},
{
menu: `<se-button id="tool_text" title="${i18next.t('tools.mode_text')}" src="${imgPath}/text.svg" shortcut="T"></se-button>`,
menu: `<se-button id="tool_text" title="tools.mode_text" src="text.svg" shortcut="T"></se-button>`,
position: 8
},
{
menu: `<se-button id="tool_image" title="${i18next.t('tools.mode_image')}" src="${imgPath}/image.svg"></se-button>`,
menu: `<se-button id="tool_image" title="tools.mode_image" src="image.svg"></se-button>`,
position: 11
}
];
@ -269,10 +267,7 @@ class LeftPanel {
$id("tool_fhrect").addEventListener("click", this.clickFHRect.bind(this));
$id("tool_ellipse").addEventListener("click", this.clickEllipse.bind(this));
$id("tool_circle").addEventListener("click", this.clickCircle.bind(this));
$id("tool_fhellipse").addEventListener(
"click",
this.clickFHEllipse.bind(this)
);
$id("tool_fhellipse").addEventListener("click", this.clickFHEllipse.bind(this));
}
}

View File

@ -111,18 +111,20 @@ class TopPanel {
$id("stroke_width").value = this.selectedElement.getAttribute("stroke-width") || 1;
$id("stroke_style").value = this.selectedElement.getAttribute("stroke-dasharray") || "none";
$id("stroke_style").setAttribute("value", $id("stroke_style").value);
let attr =
this.selectedElement.getAttribute("stroke-linejoin") || "miter";
if ($id("linejoin_" + attr).length) {
if ($id("linejoin_" + attr)) {
this.setStrokeOpt($id("linejoin_" + attr));
$id("stroke_linejoin").setAttribute("value", attr);
}
attr = this.selectedElement.getAttribute("stroke-linecap") || "butt";
if ($id("linecap_" + attr).length) {
if ($id("linecap_" + attr)) {
this.setStrokeOpt($id("linecap_" + attr));
$id("stroke_linecap").setAttribute("value", attr);
}
}
}
@ -343,7 +345,7 @@ class TopPanel {
this.displayTool("text_panel");
$id("tool_italic").pressed = this.editor.svgCanvas.getItalic();
$id("tool_bold").pressed = this.editor.svgCanvas.getBold();
$id("tool_font_family").value = elem.getAttribute("font-family");
$id("tool_font_family").setAttribute("value", elem.getAttribute("font-family"));
$id("font_size").value = elem.getAttribute("font-size");
$id("text").value = elem.textContent;
const textAnchorStart = $id("tool_text_anchor_start");
@ -795,7 +797,6 @@ class TopPanel {
* @returns {void}
*/
togglePathEditMode(editMode, elems) {
const { imgPath } = this.editor.configObj.curConfig;
if (editMode) {
this.displayTool('path_node_panel');
} else {
@ -805,14 +806,14 @@ class TopPanel {
// Change select icon
$id('tool_path').pressed = false;
$id('tool_select').pressed = true;
$id('tool_select').setAttribute('src', `${imgPath}/select_node.svg`);
$id('tool_select').setAttribute('src', `select_node.svg`);
this.editor.multiselected = false;
if (elems.length) {
this.editor.selectedElement = elems[0];
}
} else {
setTimeout(() => {
$id('tool_select').setAttribute('src', `${imgPath}/select.svg`);
$id('tool_select').setAttribute('src', `select.svg`);
}, 1000);
}
}
@ -824,101 +825,75 @@ class TopPanel {
// add Top panel
const template = document.createElement("template");
const { i18next } = this.editor;
const { imgPath } = this.editor.configObj.curConfig;
// eslint-disable-next-line no-unsanitized/property
template.innerHTML = `
<div id="tools_top">
<div id="editor_panel">
<div class="tool_sep"></div>
<se-button
id="tool_source"
title="${i18next.t('tools.tool_source')}"
shortcut="U"
src="${imgPath}/source.svg"
></se-button>
<se-button
id="tool_wireframe"
title="${i18next.t('tools.wireframe_mode')}"
shortcut="F"
src="${imgPath}/wireframe.svg"
></se-button>
<se-button id="tool_source" title="tools.tool_source" shortcut="U" src="source.svg"></se-button>
<se-button id="tool_wireframe" title="tools.wireframe_mode" shortcut="F" src="wireframe.svg"></se-button>
</div> <!-- editor_panel -->
<div id="history_panel">
<div class="tool_sep"></div>
<se-button id="tool_undo" title="${i18next.t('tools.undo')}" shortcut="Z" src="${imgPath}/undo.svg" disabled></se-button>
<se-button id="tool_redo" title="${i18next.t('tools.redo')}" shortcut="Y" src="${imgPath}/redo.svg" disabled></se-button>
<se-button id="tool_undo" title="tools.undo" shortcut="Z" src="undo.svg" disabled></se-button>
<se-button id="tool_redo" title="tools.redo" shortcut="Y" src="redo.svg" disabled></se-button>
</div> <!-- history_panel -->
<!-- Buttons when a single element is selected -->
<div class="selected_panel">
<div class="tool_sep"></div>
<se-button id="tool_clone" title="${i18next.t('tools.clone')}" shortcut="D" src="${imgPath}/clone.svg"></se-button>
<se-button id="tool_delete" title="${i18next.t('tools.del')}" shortcut="Delete/Backspace" src="${imgPath}/delete.svg"></se-button>
<se-button id="tool_clone" title="tools.clone" shortcut="D" src="clone.svg"></se-button>
<se-button id="tool_delete" title="tools.del" shortcut="Delete/Backspace" src="delete.svg"></se-button>
</div>
<div class="selected_panel">
<div class="tool_sep"></div>
<se-button id="tool_move_top" title="${i18next.t('tools.move_top')}" shortcut="Ctrl+Shift+]" src="${imgPath}/move_top.svg"></se-button>
<se-button id="tool_move_bottom" title="${i18next.t('tools.move_bottom')}" shortcut="Ctrl+Shift+[" src="${imgPath}/move_bottom.svg"></se-button>
<se-button id="tool_move_top" title="tools.move_top" shortcut="Ctrl+Shift+]" src="move_top.svg"></se-button>
<se-button id="tool_move_bottom" title="tools.move_bottom" shortcut="Ctrl+Shift+[" src="move_bottom.svg"></se-button>
</div>
<div class="selected_panel">
<se-button id="tool_topath" title="${i18next.t('tools.to_path')}" src="${imgPath}/to_path.svg"></se-button>
<se-button id="tool_reorient" title="${i18next.t('tools.reorient_path')}" src="${imgPath}/reorient.svg"></se-button>
<se-button id="tool_make_link" title="${i18next.t('tools.make_link')}" src="${imgPath}/globe_link.svg"></se-button>
<se-button id="tool_topath" title="tools.to_path" src="to_path.svg"></se-button>
<se-button id="tool_reorient" title="tools.reorient_path" src="reorient.svg"></se-button>
<se-button id="tool_make_link" title="tools.make_link" src="globe_link.svg"></se-button>
</div>
<div class="selected_panel">
<div class="tool_sep"></div>
<se-input id="elem_id" data-attr="id" size="10" label="id" title="${i18next.t('properties.id')}"></se-input>
<se-input id="elem_id" data-attr="id" size="10" label="properties.id_label" title="properties.id"></se-input>
</div>
<div class="selected_panel">
<se-input id="elem_class" data-attr="class" size="10" label="class" title="${i18next.t('properties.class')}"></se-input>
<se-spin-input size="3" id="angle" min=-180 max=180 step=5 src="${imgPath}/angle.svg"
title="${i18next.t('properties.angle')}"></se-spin-input>
<se-spin-input size="2" id="blur" min=0 max=100 step=5 src="${imgPath}/blur.svg"
title="${i18next.t('properties.blur')}"></se-spin-input>
<se-list id="tool_position" title="${i18next.t('tools.align_to_page')}" label="" width="22px" height="22px">
<se-list-item id="tool_posleft" value="l">
<img title="${i18next.t('tools.align_left')}" src="${imgPath}/align_left.svg" height="22px">
</se-list-item>
<se-list-item id="tool_poscenter" value="c">
<img title="${i18next.t('tools.align_center')}" src="${imgPath}/align_center.svg" height="22px">
</se-list-item>
<se-list-item id="tool_posright" value="r">
<img title="${i18next.t('tools.align_right')}" src="${imgPath}/align_right.svg" height="22px">
</se-list-item>
<se-list-item id="tool_postop" value="t">
<img title="${i18next.t('tools.align_top')}" src="${imgPath}/align_top.svg" height="22px">
</se-list-item>
<se-list-item id="tool_posmiddle" value="m">
<img title="${i18next.t('tools.align_middle')}" src="${imgPath}/align_middle.svg" height="22px">
</se-list-item>
<se-list-item id="tool_posbottom" value="b">
<img title="${i18next.t('tools.align_bottom')}" src="${imgPath}/align_bottom.svg" height="22px">
</se-list-item>
<se-input id="elem_class" data-attr="class" size="10" label="properties.class_label" title="properties.class"></se-input>
<se-spin-input size="3" id="angle" min=-180 max=180 step=5 src="angle.svg" title="properties.angle"></se-spin-input>
<se-spin-input size="2" id="blur" min=0 max=100 step=5 src="blur.svg" title="properties.blur"></se-spin-input>
<se-list id="tool_position" title="tools.align_to_page" label="" width="22px" height="22px">
<se-list-item id="tool_posleft" value="l" title="tools.align_left" src="align_left.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_poscenter" value="c" title="tools.align_center" src="align_center.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posright" value="r" title="tools.align_right" src="align_right.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_postop" value="t" title="tools.align_top" src="align_top.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posmiddle" value="m" title="tools.align_middle" src="align_middle.svg" img-height="22px"></se-list-item>
<se-list-item id="tool_posbottom" value="b" src="align_bottom.svg" title="tools.align_bottom" img-height="22px"></se-list-item>
</se-list>
</div>
<div class="xy_panel">
<se-spin-input id="selected_x" data-attr="x" size="4" type="text" label="x" title="${i18next.t('properties.pos_x')}">
<se-spin-input id="selected_x" data-attr="x" size="4" type="text" label="properties.x_label" title="properties.pos_x">
</se-spin-input>
<se-spin-input id="selected_y" data-attr="y" size="4" type="text" label="y" title="${i18next.t('properties.pos_y')}">
<se-spin-input id="selected_y" data-attr="y" size="4" type="text" label="properties.y_label" title="properties.pos_y">
</se-spin-input>
</div>
<!-- Buttons when multiple elements are selected -->
<div class="multiselected_panel">
<div class="tool_sep"></div>
<se-button id="tool_clone_multi" title="${i18next.t('tools.clone')}" shortcut="C" src="${imgPath}/clone.svg"></se-button>
<se-button id="tool_delete_multi" title="${i18next.t('tools.del')}" shortcut="Delete/Backspace"
src="${imgPath}/delete.svg"></se-button>
<se-button id="tool_clone_multi" title="tools.clone" shortcut="C" src="clone.svg"></se-button>
<se-button id="tool_delete_multi" title="tools.del" shortcut="Delete/Backspace" src="delete.svg"></se-button>
</div>
<div class="multiselected_panel">
<div class="tool_sep"></div>
<se-button id="tool_group_elements" title="${i18next.t('tools.group_elements')}" shortcut="G" src="${imgPath}/group_elements.svg">
<se-button id="tool_group_elements" title="tools.group_elements" shortcut="G" src="group_elements.svg">
</se-button>
<se-button id="tool_make_link_multi" title="${i18next.t('tools.make_link')}" src="${imgPath}/globe_link.svg"></se-button>
<se-button id="tool_align_left" title="${i18next.t('tools.align_left')}" src="${imgPath}/align_left.svg"></se-button>
<se-button id="tool_align_center" title="${i18next.t('tools.align_center')}" src="${imgPath}/align_center.svg"></se-button>
<se-button id="tool_align_right" title="${i18next.t('tools.align_right')}" src="${imgPath}/align_right.svg"></se-button>
<se-button id="tool_align_top" title="${i18next.t('tools.align_top')}" src="${imgPath}/align_top.svg"></se-button>
<se-button id="tool_align_middle" title="${i18next.t('tools.align_middle')}" src="${imgPath}/align_middle.svg"></se-button>
<se-button id="tool_align_bottom" title="${i18next.t('tools.align_bottom')}" src="${imgPath}/align_bottom.svg"></se-button>
<se-button id="tool_make_link_multi" title="tools.make_link" src="globe_link.svg"></se-button>
<se-button id="tool_align_left" title="tools.align_left" src="align_left.svg"></se-button>
<se-button id="tool_align_center" title="tools.align_center" src="align_center.svg"></se-button>
<se-button id="tool_align_right" title="tools.align_right" src="align_right.svg"></se-button>
<se-button id="tool_align_top" title="tools.align_top" src="align_top.svg"></se-button>
<se-button id="tool_align_middle" title="tools.align_middle" src="align_middle.svg"></se-button>
<se-button id="tool_align_bottom" title="tools.align_bottom" src="align_bottom.svg"></se-button>
<se-select id="tool_align_relative" label="relative to:"
options="${i18next.t('tools.selected_objects')},
${i18next.t('tools.largest_object')},
@ -928,54 +903,41 @@ class TopPanel {
</se-select>
</div> <!-- multiselected_panel -->
<div class="rect_panel">
<se-spin-input id="rect_width" data-attr="width" size="4" label="w" title="${i18next.t('properties.rect_width')}">
</se-spin-input>
<se-spin-input id="rect_height" data-attr="height" size="4" label="h" title="${i18next.t('properties.rect_height')}">
</se-spin-input>
<se-spin-input id="rect_rx" min=0 max=1000 step=1 size="3" title="${i18next.t('properties.corner_radius')}"
data-attr="Corner Radius" src="${imgPath}/c_radius.svg"></se-spin-input>
<se-spin-input id="rect_width" data-attr="width" size="4" label="properties.w_label" title="properties.rect_width"></se-spin-input>
<se-spin-input id="rect_height" data-attr="height" size="4" label="properties.h_label" title="properties.rect_height"></se-spin-input>
<se-spin-input id="rect_rx" min=0 max=1000 step=1 size="3" title="properties.corner_radius" data-attr="Corner Radius" src="c_radius.svg"></se-spin-input>
</div> <!-- rect_panel -->
<div class="image_panel">
<se-spin-input id="image_width" data-attr="width" size="4" type="text" label="w" title="${i18next.t('properties.image_width')}">
</se-spin-input>
<se-spin-input id="image_height" data-attr="height" size="4" type="text" label="h"
title="${i18next.t('properties.image_height')}"></se-spin-input>
<se-spin-input id="image_width" data-attr="width" size="4" type="text" label="properties.w_label" title="properties.image_width"></se-spin-input>
<se-spin-input id="image_height" data-attr="height" size="4" type="text" label="properties.h_label" title="properties.image_height"></se-spin-input>
</div>
<div class="image_panel">
<se-input id="image_url" data-attr="image_url" size="15" label="${i18next.t('properties.image_url')}"></se-input>
<se-input id="image_url" data-attr="image_url" size="15" label="properties.image_url"></se-input>
</div>
<div class="circle_panel">
<se-spin-input id="circle_cx" data-attr="cx" size="4" label="cx"></se-spin-input>
<se-spin-input id="circle_cy" data-attr="cy" size="4" label="cy"></se-spin-input>
<se-spin-input id="circle_cx" data-attr="cx" size="4" label="properties.cx_label"></se-spin-input>
<se-spin-input id="circle_cy" data-attr="cy" size="4" label="properties.cy_label"></se-spin-input>
</div>
<div class="circle_panel">
<se-spin-input id="circle_r" data-attr="r" size="4" label="r"></se-spin-input>
<se-spin-input id="circle_r" data-attr="r" size="4" label="properties.r_label"></se-spin-input>
</div>
<div class="ellipse_panel">
<se-spin-input id="ellipse_cx" data-attr="cx" size="4" title="${i18next.t('properties.ellipse_cx')}" label="cx">
</se-spin-input>
<se-spin-input id="ellipse_cy" data-attr="cy" size="4" title="${i18next.t('properties.ellipse_cy')}" label="cy">
</se-spin-input>
<se-spin-input id="ellipse_cx" data-attr="cx" size="4" title="properties.ellipse_cx" label="properties.cx_label"></se-spin-input>
<se-spin-input id="ellipse_cy" data-attr="cy" size="4" title="properties.ellipse_cy" label="properties.cy_label"></se-spin-input>
</div>
<div class="ellipse_panel">
<se-spin-input id="ellipse_rx" data-attr="rx" size="4" title="${i18next.t('properties.ellipse_rx')}" label="rx">
</se-spin-input>
<se-spin-input id="ellipse_ry" data-attr="ry" size="4" title="${i18next.t('properties.ellipse_ry')}" label="ry">
</se-spin-input>
<se-spin-input id="ellipse_rx" data-attr="rx" size="4" title="properties.ellipse_rx" label="properties.rx_label"></se-spin-input>
<se-spin-input id="ellipse_ry" data-attr="ry" size="4" title="properties.ellipse_ry" label="properties.ry_label"></se-spin-input>
</div>
<div class="line_panel">
<se-spin-input id="line_x1" data-attr="x1" size="4" title="${i18next.t('properties.line_x1')}" label="x1">
</se-spin-input>
<se-spin-input id="line_y1" data-attr="y1" size="4" title="${i18next.t('properties.line_y1')}" label="y1">
</se-spin-input>
<se-spin-input id="line_x2" data-attr="x2" size="4" title="${i18next.t('properties.line_x2')}" label="x2">
</se-spin-input>
<se-spin-input id="line_y2" data-attr="y2" size="4" title="${i18next.t('properties.line_y2')}" label="y2">
</se-spin-input>
<se-spin-input id="line_x1" data-attr="x1" size="4" title="properties.line_x1" label="properties.x1_label"></se-spin-input>
<se-spin-input id="line_y1" data-attr="y1" size="4" title="properties.line_y1" label="properties.y1_label"></se-spin-input>
<se-spin-input id="line_x2" data-attr="x2" size="4" title="properties.line_x2" label="properties.x2_label"></se-spin-input>
<se-spin-input id="line_y2" data-attr="y2" size="4" title="properties.line_y2" label="properties.y2_label"></se-spin-input>
</div>
<div class="text_panel">
<se-button id="tool_bold" title="${i18next.t('properties.bold')}" src="${imgPath}/bold.svg" shortcut="B"></se-button>
<se-button id="tool_italic" title="${i18next.t('properties.italic')}" src="${imgPath}/italic.svg" shortcut="I"></se-button>
<se-button id="tool_bold" title="properties.bold" src="bold.svg" shortcut="B"></se-button>
<se-button id="tool_italic" title="properties.italic" src="italic.svg" shortcut="I"></se-button>
<se-select id="tool_font_family" label="Font:"
options="${i18next.t('properties.serif')},
${i18next.t('properties.sans_serif')},
@ -988,28 +950,24 @@ class TopPanel {
values="Serif Sans-serif Cursive Fantasy Monospace Courier Helvetica Times"
>
</select>
<se-spin-input size="2" id="font_size" min=1 max=1000 step=1 title="${i18next.t('properties.font_size')}"
src="${imgPath}/fontsize.svg"></se-spin-input>
<se-spin-input size="2" id="font_size" min=1 max=1000 step=1 title="properties.font_size" src="fontsize.svg"></se-spin-input>
</div>
<div class="text_panel">
<se-button id="tool_text_anchor_start" title="${i18next.t('properties.text_anchor_start')}" src="${imgPath}/anchor_start.svg"></se-button>
<se-button id="tool_text_anchor_middle" title="${i18next.t('properties.text_anchor_middle')}" src="${imgPath}/anchor_middle.svg"></se-button>
<se-button id="tool_text_anchor_end" title="${i18next.t('properties.text_anchor_end')}" src="${imgPath}/anchor_end.svg"></se-button>
<se-button id="tool_text_anchor_start" title="properties.text_anchor_start" src="anchor_start.svg"></se-button>
<se-button id="tool_text_anchor_middle" title="properties.text_anchor_middle" src="anchor_middle.svg"></se-button>
<se-button id="tool_text_anchor_end" title="properties.text_anchor_end" src="anchor_end.svg"></se-button>
</div>
<!-- Not visible, but still used -->
<input id="text" type="text" size="35" />
<div class="container_panel">
<div class="tool_sep"></div>
<se-input id="g_title" data-attr="title" size="8" label="${i18next.t('label')}"></se-input>
<se-input id="g_title" data-attr="title" size="8" label="properties.label"></se-input>
</div> <!-- container_panel -->
<div class="use_panel">
<se-button id="tool_unlink_use" title="${i18next.t('tools.tool_unlink_use')}"
src="${imgPath}/unlink_use.svg">
</se-button>
<se-button id="tool_unlink_use" title="tools.tool_unlink_use" src="unlink_use.svg"></se-button>
</div> <!-- use_panel -->
<div class="g_panel">
<se-button id="tool_ungroup" title="${i18next.t('tools.ungroup')}" src="${imgPath}/ungroup.svg">
</se-button>
<se-button id="tool_ungroup" title="tools.ungroup" src="ungroup.svg"></se-button>
</div> <!-- g_panel -->
<!-- For anchor elements -->
<div class="a_panel">
@ -1020,23 +978,15 @@ class TopPanel {
</div> <!-- a_panel -->
<div class="path_node_panel">
<div class="tool_sep"></div>
<se-button id="tool_node_link" title="${i18next.t('tools.node_link')}" src="${imgPath}/tool_node_link.svg" pressed>
</se-button>
<se-button id="tool_node_link" title="tools.node_link" src="tool_node_link.svg" pressed></se-button>
<div class="tool_sep"></div>
<se-spin-input id="path_node_x" data-attr="x" size="4" title="${i18next.t('properties.node_x')}" label="x:">
</se-spin-input>
<se-spin-input id="path_node_y" data-attr="y" size="4" title="${i18next.t('properties.node_y')}" label="y:">
</se-spin-input>
<se-select id="seg_type" title="${i18next.t('tools.seg_type')}" label=""
options="${i18next.t('properties.straight_segments')}, ${i18next.t('properties.curve_segments')}"
values="4 6"
>
</se-select>
<se-button id="tool_node_clone" title="${i18next.t('tools.node_clone')}" src="${imgPath}/tool_node_clone.svg"></se-button>
<se-button id="tool_node_delete" title="${i18next.t('tools.node_delete')}" src="${imgPath}/tool_node_delete.svg"></se-button>
<se-button id="tool_openclose_path" title="${i18next.t('tools.openclose_path')}" src="${imgPath}/tool_openclose_path.svg">
</se-button>
<se-button id="tool_add_subpath" title="${i18next.t('tools.add_subpath')}" src="${imgPath}/tool_add_subpath.svg"></se-button>
<se-spin-input id="path_node_x" data-attr="x" size="4" title="properties.node_x" label="properties.x_label"></se-spin-input>
<se-spin-input id="path_node_y" data-attr="y" size="4" title="properties.node_y" label="properties.y_label"></se-spin-input>
<se-select id="seg_type" title="${i18next.t('tools.seg_type')}" label="" options="${i18next.t('properties.straight_segments')}, ${i18next.t('properties.curve_segments')}" values="4 6"></se-select>
<se-button id="tool_node_clone" title="tools.node_clone" src="tool_node_clone.svg"></se-button>
<se-button id="tool_node_delete" title="tools.node_delete" src="tool_node_delete.svg"></se-button>
<se-button id="tool_openclose_path" title="tools.openclose_path" src="tool_openclose_path.svg"></se-button>
<se-button id="tool_add_subpath" title="tools.add_subpath" src="tool_add_subpath.svg"></se-button>
</div> <!-- path_node_panel -->
<div id="cur_context_panel"></div>
</div>
@ -1050,121 +1000,45 @@ class TopPanel {
this.editor.$container.append(newSeEditorDialog);
newSeEditorDialog.init(i18next);
// register action to top panel buttons
$id("tool_source").addEventListener(
"click",
this.showSourceEditor.bind(this)
);
$id("tool_wireframe").addEventListener(
"click",
this.clickWireframe.bind(this)
);
$id("tool_source").addEventListener("click", this.showSourceEditor.bind(this));
$id("tool_wireframe").addEventListener("click", this.clickWireframe.bind(this));
$id("tool_undo").addEventListener("click", this.clickUndo.bind(this));
$id("tool_redo").addEventListener("click", this.clickRedo.bind(this));
$id("tool_clone").addEventListener("click", this.clickClone.bind(this));
$id("tool_clone_multi").addEventListener(
"click",
this.clickClone.bind(this)
);
$id("tool_delete").addEventListener(
"click",
this.deleteSelected.bind(this)
);
$id("tool_delete_multi").addEventListener(
"click",
this.deleteSelected.bind(this)
);
$id("tool_move_top").addEventListener(
"click",
this.moveToTopSelected.bind(this)
);
$id("tool_move_bottom").addEventListener(
"click",
this.moveToBottomSelected.bind(this)
);
$id("tool_clone_multi").addEventListener("click", this.clickClone.bind(this));
$id("tool_delete").addEventListener("click", this.deleteSelected.bind(this));
$id("tool_delete_multi").addEventListener("click", this.deleteSelected.bind(this));
$id("tool_move_top").addEventListener("click", this.moveToTopSelected.bind(this));
$id("tool_move_bottom").addEventListener("click", this.moveToBottomSelected.bind(this));
$id("tool_topath").addEventListener("click", this.convertToPath.bind(this));
$id("tool_make_link").addEventListener(
"click",
this.makeHyperlink.bind(this)
);
$id("tool_make_link_multi").addEventListener(
"click",
this.makeHyperlink.bind(this)
);
$id("tool_reorient").addEventListener(
"click",
this.reorientPath.bind(this)
);
$id("tool_group_elements").addEventListener(
"click",
this.clickGroup.bind(this)
);
$id("tool_position").addEventListener("change", (evt) =>
this.clickAlignEle.bind(this)(evt)
);
$id("tool_align_left").addEventListener("click", () =>
this.clickAlign.bind(this)("left")
);
$id("tool_align_right").addEventListener("click", () =>
this.clickAlign.bind(this)("right")
);
$id("tool_align_center").addEventListener("click", () =>
this.clickAlign.bind(this)("center")
);
$id("tool_align_top").addEventListener("click", () =>
this.clickAlign.bind(this)("top")
);
$id("tool_align_bottom").addEventListener("click", () =>
this.clickAlign.bind(this)("bottom")
);
$id("tool_align_middle").addEventListener("click", () =>
this.clickAlign.bind(this)("middle")
);
$id("tool_node_clone").addEventListener(
"click",
this.clonePathNode.bind(this)
);
$id("tool_node_delete").addEventListener(
"click",
this.deletePathNode.bind(this)
);
$id("tool_openclose_path").addEventListener(
"click",
this.opencloseSubPath.bind(this)
);
$id("tool_add_subpath").addEventListener(
"click",
this.addSubPath.bind(this)
);
$id("tool_node_link").addEventListener(
"click",
this.linkControlPoints.bind(this)
);
$id("angle").addEventListener(
"change",
this.changeRotationAngle.bind(this)
);
$id("tool_make_link").addEventListener("click", this.makeHyperlink.bind(this));
$id("tool_make_link_multi").addEventListener("click", this.makeHyperlink.bind(this));
$id("tool_reorient").addEventListener("click", this.reorientPath.bind(this));
$id("tool_group_elements").addEventListener("click", this.clickGroup.bind(this));
$id("tool_position").addEventListener("change", (evt) => this.clickAlignEle.bind(this)(evt));
$id("tool_align_left").addEventListener("click", () => this.clickAlign.bind(this)("left"));
$id("tool_align_right").addEventListener("click", () => this.clickAlign.bind(this)("right"));
$id("tool_align_center").addEventListener("click", () => this.clickAlign.bind(this)("center"));
$id("tool_align_top").addEventListener("click", () => this.clickAlign.bind(this)("top"));
$id("tool_align_bottom").addEventListener("click", () => this.clickAlign.bind(this)("bottom"));
$id("tool_align_middle").addEventListener("click", () => this.clickAlign.bind(this)("middle"));
$id("tool_node_clone").addEventListener("click", this.clonePathNode.bind(this));
$id("tool_node_delete").addEventListener("click", this.deletePathNode.bind(this));
$id("tool_openclose_path").addEventListener("click", this.opencloseSubPath.bind(this));
$id("tool_add_subpath").addEventListener("click", this.addSubPath.bind(this));
$id("tool_node_link").addEventListener("click", this.linkControlPoints.bind(this));
$id("angle").addEventListener("change", this.changeRotationAngle.bind(this));
$id("blur").addEventListener("change", this.changeBlur.bind(this));
$id("rect_rx").addEventListener("change", this.changeRectRadius.bind(this));
$id("font_size").addEventListener("change", this.changeFontSize.bind(this));
$id("tool_ungroup").addEventListener("click", this.clickGroup.bind(this));
$id("tool_bold").addEventListener("click", this.clickBold.bind(this));
$id("tool_italic").addEventListener("click", this.clickItalic.bind(this));
$id("tool_text_anchor_start").addEventListener("click", () =>
this.clickTextAnchor.bind(this)("start")
);
$id("tool_text_anchor_middle").addEventListener("click", () =>
this.clickTextAnchor.bind(this)("middle")
);
$id("tool_text_anchor_end").addEventListener("click", () =>
this.clickTextAnchor.bind(this)("end")
);
$id("tool_unlink_use").addEventListener(
"click",
this.clickGroup.bind(this)
);
$id('image_url').addEventListener('change', (evt) => {
this.setImageURL(evt.currentTarget.value);
});
$id("tool_text_anchor_start").addEventListener("click", () => this.clickTextAnchor.bind(this)("start"));
$id("tool_text_anchor_middle").addEventListener("click", () => this.clickTextAnchor.bind(this)("middle"));
$id("tool_text_anchor_end").addEventListener("click", () => this.clickTextAnchor.bind(this)("end"));
$id("tool_unlink_use").addEventListener("click", this.clickGroup.bind(this));
$id('image_url').addEventListener('change', (evt) => { this.setImageURL(evt.currentTarget.value);});
// all top panel attributes
[