/* eslint-disable max-len */
/* globals seAlert */
import SvgCanvas from '@svgedit/svgcanvas'
import topPanelHTML from './TopPanel.html'
const { $qa, $id, $click, isValidUnit, getTypeMap, convertUnit } = SvgCanvas
/*
* register actions for left panel
*/
/**
*
*/
class TopPanel {
/**
* @param {PlainObject} editor svgedit handler
*/
constructor (editor) {
this.editor = editor
}
/**
* @type {module}
*/
displayTool (className) {
// default display is 'none' so removing the property will make the panel visible
$qa(`.${className}`).map(el => el.style.removeProperty('display'))
}
/**
* @type {module}
*/
hideTool (className) {
$qa(`.${className}`).forEach(el => {
el.style.display = 'none'
})
}
/**
* @type {module}
*/
get selectedElement () {
return this.editor.selectedElement
}
/**
* @type {module}
*/
get multiselected () {
return this.editor.multiselected
}
/**
* @type {module}
*/
get path () {
return this.editor.svgCanvas.pathActions
}
/**
*
* @param {Element} opt
* @param {boolean} changeElem
* @returns {void}
*/
setStrokeOpt (opt, changeElem) {
const { id } = opt
const bits = id.split('_')
const [pre, val] = bits
if (changeElem) {
this.svgCanvas.setStrokeAttr('stroke-' + pre, val)
}
opt.classList.add('current')
const elements = Array.prototype.filter.call(
opt.parentNode.children,
function (child) {
return child !== opt
}
)
Array.from(elements).forEach(function (element) {
element.classList.remove('current')
})
}
/**
* Updates the toolbar (colors, opacity, etc) based on the selected element.
* This function also updates the opacity and id elements that are in the
* context panel.
* @returns {void}
*/
update () {
let i
let len
// set title
$qa('#title_panel > p')[0].textContent = this.editor.title
if (this.selectedElement) {
switch (this.selectedElement.tagName) {
case 'use':
case 'image':
case 'foreignObject':
break
case 'g':
case 'a': {
// Look for common styles
const childs = this.selectedElement.getElementsByTagName('*')
let gWidth = null
for (i = 0, len = childs.length; i < len; i++) {
const swidth = childs[i].getAttribute('stroke-width')
if (i === 0) {
gWidth = swidth
} else if (gWidth !== swidth) {
gWidth = null
}
}
$id('stroke_width').value = gWidth === null ? '' : gWidth
this.editor.bottomPanel.updateColorpickers(false)
break
}
default: {
this.editor.bottomPanel.updateColorpickers(false)
$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)) {
this.setStrokeOpt($id('linejoin_' + attr))
$id('stroke_linejoin').setAttribute('value', attr)
}
attr = this.selectedElement.getAttribute('stroke-linecap') || 'butt'
if ($id('linecap_' + attr)) {
this.setStrokeOpt($id('linecap_' + attr))
$id('stroke_linecap').setAttribute('value', attr)
}
}
}
}
// All elements including image and group have opacity
if (this.selectedElement) {
const opacPerc =
(this.selectedElement.getAttribute('opacity') || 1.0) * 100
$id('opacity').value = opacPerc
$id('elem_id').value = this.selectedElement.id
$id('elem_class').value = this.selectedElement.getAttribute('class') ?? ''
}
this.editor.bottomPanel.updateToolButtonState()
}
/**
* @param {PlainObject} [opts={}]
* @param {boolean} [opts.cancelDeletes=false]
* @returns {void} Resolves to `undefined`
*/
promptImgURL ({ cancelDeletes = false } = {}) {
let curhref = this.editor.svgCanvas.getHref(this.editor.selectedElement)
curhref = curhref.startsWith('data:') ? '' : curhref
const url = prompt(
this.editor.i18next.t('notification.enterNewImgURL'),
curhref
)
if (url) {
this.setImageURL(url)
} else if (cancelDeletes) {
this.editor.svgCanvas.deleteSelectedElements()
}
}
/**
* Updates the context panel tools based on the selected element.
* @returns {void}
*/
updateContextPanel () {
let elem = this.editor.selectedElement
// If element has just been deleted, consider it null
if (!elem?.parentNode) {
elem = null
}
const currentLayerName = this.editor.svgCanvas
.getCurrentDrawing()
.getCurrentLayerName()
const currentMode = this.editor.svgCanvas.getMode()
const unit =
this.editor.configObj.curConfig.baseUnit !== 'px'
? this.editor.configObj.curConfig.baseUnit
: null
const isNode = currentMode === 'pathedit'
const menuItems = document.getElementById('se-cmenu_canvas')
this.hideTool('selected_panel')
this.hideTool('multiselected_panel')
this.hideTool('g_panel')
this.hideTool('rect_panel')
this.hideTool('circle_panel')
this.hideTool('ellipse_panel')
this.hideTool('line_panel')
this.hideTool('text_panel')
this.hideTool('image_panel')
this.hideTool('container_panel')
this.hideTool('use_panel')
this.hideTool('a_panel')
this.hideTool('xy_panel')
if (elem) {
const elname = elem.nodeName
const angle = this.editor.svgCanvas.getRotationAngle(elem)
$id('angle').value = angle
const blurval = this.editor.svgCanvas.getBlur(elem) * 10
$id('blur').value = blurval
if (
this.editor.svgCanvas.addedNew &&
elname === 'image' &&
this.editor.svgCanvas.getMode() === 'image' &&
!this.editor.svgCanvas.getHref(elem).startsWith('data:')
) {
/* await */ this.promptImgURL({ cancelDeletes: true })
}
if (!isNode && currentMode !== 'pathedit') {
this.displayTool('selected_panel')
// Elements in this array already have coord fields
if (['line', 'circle', 'ellipse'].includes(elname)) {
this.hideTool('xy_panel')
} else {
let x
let y
// Get BBox vals for g, polyline and path
if (['g', 'polyline', 'path'].includes(elname)) {
const bb = this.editor.svgCanvas.getStrokedBBox([elem])
if (bb) {
;({ x, y } = bb)
}
} else {
x = elem.getAttribute('x')
y = elem.getAttribute('y')
}
if (unit) {
x = convertUnit(x)
y = convertUnit(y)
}
$id('selected_x').value = x || 0
$id('selected_y').value = y || 0
this.displayTool('xy_panel')
}
// Elements in this array cannot be converted to a path
if (['image', 'text', 'path', 'g', 'use'].includes(elname)) {
this.hideTool('tool_topath')
} else {
this.displayTool('tool_topath')
}
if (elname === 'path') {
this.displayTool('tool_reorient')
} else {
this.hideTool('tool_reorient')
}
$id('tool_reorient').disabled = angle === 0
} else {
const point = this.path.getNodePoint()
$id('tool_add_subpath').pressed = false
!this.path.canDeleteNodes
? $id('tool_node_delete').classList.add('disabled')
: $id('tool_node_delete').classList.remove('disabled')
// Show open/close button based on selected point
// setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path');
if (point) {
const segType = $id('seg_type')
if (unit) {
point.x = convertUnit(point.x)
point.y = convertUnit(point.y)
}
$id('path_node_x').value = point.x
$id('path_node_y').value = point.y
if (point.type) {
segType.value = point.type
segType.removeAttribute('disabled')
} else {
segType.value = 4
segType.setAttribute('disabled', 'disabled')
}
}
return
}
// update contextual tools here
const panels = {
g: [],
a: [],
rect: ['rx', 'width', 'height'],
image: ['width', 'height'],
circle: ['cx', 'cy', 'r'],
ellipse: ['cx', 'cy', 'rx', 'ry'],
line: ['x1', 'y1', 'x2', 'y2'],
text: [],
use: []
}
const { tagName } = elem
let linkHref = null
if (tagName === 'a') {
linkHref = this.editor.svgCanvas.getHref(elem)
this.displayTool('g_panel')
}
// siblings
if (elem.parentNode) {
const selements = Array.prototype.filter.call(
elem.parentNode.children,
function (child) {
return child !== elem
}
)
if (elem.parentNode.tagName === 'a' && !selements.length) {
this.displayTool('a_panel')
linkHref = this.editor.svgCanvas.getHref(elem.parentNode)
}
}
// Hide/show the make_link buttons
if (linkHref) {
this.displayTool('tool_make_link')
this.displayTool('tool_make_link_multi')
$id('link_url').value = linkHref
} else {
this.hideTool('tool_make_link')
this.hideTool('tool_make_link_multi')
}
if (panels[tagName]) {
const curPanel = panels[tagName]
this.displayTool(tagName + '_panel')
curPanel.forEach(item => {
let attrVal = elem.getAttribute(item)
if (this.editor.configObj.curConfig.baseUnit !== 'px' && elem[item]) {
const bv = elem[item].baseVal.value
attrVal = convertUnit(bv)
}
$id(`${tagName}_${item}`).value = attrVal || 0
})
if (tagName === 'text') {
this.displayTool('text_panel')
$id('tool_italic').pressed = this.editor.svgCanvas.getItalic()
$id('tool_bold').pressed = this.editor.svgCanvas.getBold()
$id(
'tool_text_decoration_underline'
).pressed = this.editor.svgCanvas.hasTextDecoration('underline')
$id(
'tool_text_decoration_linethrough'
).pressed = this.editor.svgCanvas.hasTextDecoration('line-through')
$id(
'tool_text_decoration_overline'
).pressed = this.editor.svgCanvas.hasTextDecoration('overline')
$id('tool_font_family').value = elem.getAttribute('font-family')
$id('tool_text_anchor').setAttribute(
'value',
elem.getAttribute('text-anchor')
)
$id('font_size').value = elem.getAttribute('font-size')
$id('tool_letter_spacing').value =
elem.getAttribute('letter-spacing') ?? 0
$id('tool_word_spacing').value =
elem.getAttribute('word-spacing') ?? 0
$id('tool_text_length').value = elem.getAttribute('textLength') ?? 0
$id('tool_length_adjust').value =
elem.getAttribute('lengthAdjust') ?? 0
$id('text').value = elem.textContent
if (this.editor.svgCanvas.addedNew) {
// Timeout needed for IE9
setTimeout(() => {
$id('text').focus()
$id('text').select()
}, 100)
}
// text
} else if (
tagName === 'image' &&
this.editor.svgCanvas.getMode() === 'image'
) {
this.editor.svgCanvas.setImageURL(this.editor.svgCanvas.getHref(elem))
// image
} else if (tagName === 'g' || tagName === 'use') {
this.displayTool('container_panel')
const title = this.editor.svgCanvas.getTitle()
const label = $id('g_title')
label.value = title
$id('g_title').disabled = tagName === 'use'
}
}
menuItems.setAttribute(
(tagName === 'g' ? 'en' : 'dis') + 'ablemenuitems',
'#ungroup'
)
menuItems.setAttribute(
(tagName === 'g' || !this.multiselected ? 'dis' : 'en') +
'ablemenuitems',
'#group'
)
// if (elem)
} else if (this.multiselected) {
// Check if all selected elements are 'text' nodes, if yes enable text panel
const selElems = this.editor.svgCanvas.getSelectedElements()
if (selElems.every((elem) => elem.tagName === 'text')) {
this.displayTool('text_panel')
}
this.displayTool('multiselected_panel')
menuItems.setAttribute('enablemenuitems', '#group')
menuItems.setAttribute('disablemenuitems', '#ungroup')
} else {
menuItems.setAttribute(
'disablemenuitems',
'#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back'
)
}
// update history buttons
$id('tool_undo').disabled =
this.editor.svgCanvas.undoMgr.getUndoStackSize() === 0
$id('tool_redo').disabled =
this.editor.svgCanvas.undoMgr.getRedoStackSize() === 0
this.editor.svgCanvas.addedNew = false
if ((elem && !isNode) || this.multiselected) {
// update the selected elements' layer
$id('selLayerNames').removeAttribute('disabled')
$id('selLayerNames').value = currentLayerName
$id('selLayerNames').setAttribute('value', currentLayerName)
// Enable regular menu options
const canCMenu = document.getElementById('se-cmenu_canvas')
canCMenu.setAttribute(
'enablemenuitems',
'#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back'
)
} else {
$id('selLayerNames').setAttribute('disabled', 'disabled')
}
}
/**
* @param {Event} [e] Not used.
* @param {boolean} forSaving
* @returns {void}
*/
showSourceEditor (e, forSaving) {
const $editorDialog = document.getElementById('se-svg-editor-dialog')
if ($editorDialog.getAttribute('dialog') === 'open') return
const origSource = this.editor.svgCanvas.getSvgString()
$editorDialog.setAttribute('dialog', 'open')
$editorDialog.setAttribute('value', origSource)
$editorDialog.setAttribute('copysec', Boolean(forSaving))
$editorDialog.setAttribute('applysec', !forSaving)
}
/**
*
* @returns {void}
*/
clickWireframe () {
$id('tool_wireframe').pressed = !$id('tool_wireframe').pressed
this.editor.workarea.classList.toggle('wireframe')
const wfRules = $id('wireframe_rules')
if (!wfRules) {
const fcRules = document.createElement('style')
fcRules.setAttribute('id', 'wireframe_rules')
document.getElementsByTagName('head')[0].appendChild(fcRules)
} else {
while (wfRules.firstChild) {
wfRules.removeChild(wfRules.firstChild)
}
}
this.editor.updateWireFrame()
}
/**
*
* @returns {void}
*/
clickUndo () {
const { undoMgr, textActions } = this.editor.svgCanvas
if (undoMgr.getUndoStackSize() > 0) {
undoMgr.undo()
this.editor.layersPanel.populateLayers()
if (this.editor.svgCanvas.getMode() === 'textedit') {
textActions.clear()
}
}
}
/**
*
* @returns {void}
*/
clickRedo () {
const { undoMgr } = this.editor.svgCanvas
if (undoMgr.getRedoStackSize() > 0) {
undoMgr.redo()
this.editor.layersPanel.populateLayers()
}
}
/**
* @type {module}
*/
changeRectRadius (e) {
this.editor.svgCanvas.setRectRadius(e.target.value)
}
/**
* @type {module}
*/
changeFontSize (e) {
this.editor.svgCanvas.setFontSize(e.target.value)
}
/**
* @type {module}
*/
changeRotationAngle (e) {
this.editor.svgCanvas.setRotationAngle(e.target.value)
if (Number.parseInt(e.target.value) === 0) {
$id('tool_reorient').classList.add('disabled')
} else {
$id('tool_reorient').classList.remove('disabled')
}
}
/**
* @param {PlainObject} e
* @returns {void}
*/
changeBlur (e) {
this.editor.svgCanvas.setBlur(e.target.value / 10, true)
}
/**
*
* @returns {void}
*/
clickGroup () {
// group
if (this.editor.multiselected) {
this.editor.svgCanvas.groupSelectedElements()
// ungroup
} else if (this.editor.selectedElement) {
this.editor.svgCanvas.ungroupSelectedElement()
}
}
/**
*
* @returns {void}
*/
clickClone () {
this.editor.svgCanvas.cloneSelectedElements(20, 20)
}
/**
* @param {PlainObject} evt
* @returns {void}
*/
clickAlignEle (evt) {
this.editor.svgCanvas.alignSelectedElements(evt.detail.value, 'page')
}
/**
* @param {string} pos indicate the alignment relative to top, bottom, middle etc..
* @returns {void}
*/
clickAlign (pos) {
let value = $id('tool_align_relative').value
if (value === '') {
value = 'selected'
}
this.editor.svgCanvas.alignSelectedElements(pos, value)
}
/**
*
* @type {module}
*/
attrChanger (e) {
const attr = e.target.getAttribute('data-attr')
let val = e.target.value
const valid = isValidUnit(attr, val, this.selectedElement)
if (!valid) {
e.target.value = this.selectedElement.getAttribute(attr)
alert(this.editor.i18next.t('notification.invalidAttrValGiven'))
return false
}
if (attr !== 'id' && attr !== 'class') {
if (isNaN(val)) {
val = this.editor.svgCanvas.convertToNum(attr, val)
} else if (this.editor.configObj.curConfig.baseUnit !== 'px') {
// Convert unitless value to one with given unit
const unitData = getTypeMap()
if (
this.editor.selectedElement[attr] ||
this.editor.svgCanvas.getMode() === 'pathedit' ||
attr === 'x' ||
attr === 'y'
) {
val *= unitData[this.editor.configObj.curConfig.baseUnit]
}
}
}
this.editor.svgCanvas.changeSelectedAttribute(attr, val)
return true
}
/**
*
* @returns {void}
*/
convertToPath () {
if (this.editor.selectedElement) {
this.editor.svgCanvas.convertToPath()
}
}
/**
*
* @returns {void}
*/
reorientPath () {
if (this.editor.selectedElement) {
this.path.reorient()
}
}
/**
*
* @returns {void} Resolves to `undefined`
*/
makeHyperlink () {
if (this.editor.selectedElement || this.multiselected) {
const url = prompt(
this.editor.i18next.t('notification.enterNewLinkURL'),
'http://'
)
if (url) {
this.editor.svgCanvas.makeHyperlink(url)
}
}
}
/**
*
* @returns {void}
*/
linkControlPoints () {
$id('tool_node_link').pressed = !$id('tool_node_link').pressed
const linked = !!$id('tool_node_link').pressed
this.path.linkControlPoints(linked)
}
/**
*
* @returns {void}
*/
clonePathNode () {
if (this.path.getNodePoint()) {
this.path.clonePathNode()
}
}
/**
*
* @returns {void}
*/
deletePathNode () {
if (this.path.getNodePoint()) {
this.path.deletePathNode()
}
}
/**
*
* @returns {void}
*/
addSubPath () {
const button = $id('tool_add_subpath')
const sp = !button.classList.contains('pressed')
button.pressed = sp
// button.toggleClass('push_button_pressed tool_button');
this.path.addSubPath(sp)
}
/**
*
* @returns {void}
*/
opencloseSubPath () {
this.path.opencloseSubPath()
}
/**
* Delete is a contextual tool that only appears in the ribbon if
* an element has been selected.
* @returns {void}
*/
deleteSelected () {
if (this.editor.selectedElement || this.editor.multiselected) {
this.editor.svgCanvas.deleteSelectedElements()
}
}
/**
*
* @returns {void}
*/
moveToTopSelected () {
if (this.editor.selectedElement) {
this.editor.svgCanvas.moveToTopSelectedElement()
}
}
/**
*
* @returns {void}
*/
moveToBottomSelected () {
if (this.editor.selectedElement) {
this.editor.svgCanvas.moveToBottomSelectedElement()
}
}
/**
*
* @returns {false}
*/
clickBold () {
this.editor.svgCanvas.setBold(!this.editor.svgCanvas.getBold())
this.updateContextPanel()
return false
}
/**
*
* @returns {false}
*/
clickItalic () {
this.editor.svgCanvas.setItalic(!this.editor.svgCanvas.getItalic())
this.updateContextPanel()
return false
}
/**
* Handles the click on the text decoration buttons
*
* @param value The text decoration value
* @returns {boolean} false
*/
clickTextDecoration (value) {
if (this.editor.svgCanvas.hasTextDecoration(value)) {
this.editor.svgCanvas.removeTextDecoration(value)
} else {
this.editor.svgCanvas.addTextDecoration(value)
}
this.updateContextPanel()
return false
}
/**
* Sets the text anchor value
*
* @returns {false}
*/
clickTextAnchor (evt) {
this.editor.svgCanvas.setTextAnchor(evt.detail.value)
return false
}
/**
* @type {module}
*/
changeLetterSpacing (e) {
this.editor.svgCanvas.setLetterSpacing(e.target.value)
}
/**
* @type {module}
*/
changeWordSpacing (e) {
this.editor.svgCanvas.setWordSpacing(e.target.value)
}
/**
* @type {module}
*/
changeTextLength (e) {
this.editor.svgCanvas.setTextLength(e.target.value)
}
/**
* @type {module}
*/
changeLengthAdjust (evt) {
this.editor.svgCanvas.setLengthAdjust(evt.detail.value)
}
/**
* Set a selected image's URL.
* @function module:SVGthis.setImageURL
* @param {string} url
* @returns {void}
*/
setImageURL (url) {
const { editor } = this
if (!url) {
url = editor.defaultImageURL
}
editor.svgCanvas.setImageURL(url)
$id('image_url').value = url
if (url.startsWith('data:')) {
// data URI found
this.hideTool('image_url')
} else {
// regular URL
const promised = editor.svgCanvas.embedImage(url)
// eslint-disable-next-line promise/catch-or-return
promised
// eslint-disable-next-line promise/always-return
.then(
() => {
// switch into "select" mode if we've clicked on an element
editor.svgCanvas.setMode('select')
editor.svgCanvas.selectOnly(
editor.svgCanvas.getSelectedElements(),
true
)
},
error => {
console.error('error =', error)
seAlert(editor.i18next.t('tools.no_embed'))
editor.svgCanvas.deleteSelectedElements()
}
)
this.displayTool('image_url')
}
}
/**
*
*/
updateTitle (title) {
if (title) this.editor.title = title
const titleElement = $qa('#title_panel > p')[0]
if (titleElement) titleElement.textContent = this.editor.title
}
/**
* @param {boolean} editmode
* @param {module:svgcanvas.SvgCanvas#event:selected} elems
* @returns {void}
*/
togglePathEditMode (editMode, elems) {
if (editMode) {
this.displayTool('path_node_panel')
} else {
this.hideTool('path_node_panel')
}
if (editMode) {
// Change select icon
$id('tool_path').pressed = false
$id('tool_select').pressed = true
$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', 'select.svg')
}, 1000)
}
}
/**
* @type {module}
*/
init () {
// add Top panel
const template = document.createElement('template')
const { i18next } = this.editor
template.innerHTML = topPanelHTML
this.editor.$svgEditor.append(template.content.cloneNode(true))
// svg editor source dialoag added to DOM
const newSeEditorDialog = document.createElement(
'se-svg-source-editor-dialog'
)
newSeEditorDialog.setAttribute('id', 'se-svg-editor-dialog')
this.editor.$container.append(newSeEditorDialog)
this.updateTitle()
newSeEditorDialog.init(i18next)
$id('tool_link_url').setAttribute('title', i18next.t('tools.set_link_url'))
// register action to top panel buttons
$click($id('tool_source'), this.showSourceEditor.bind(this))
$click($id('tool_wireframe'), this.clickWireframe.bind(this))
$click($id('tool_undo'), this.clickUndo.bind(this))
$click($id('tool_redo'), this.clickRedo.bind(this))
$click($id('tool_clone'), this.clickClone.bind(this))
$click($id('tool_clone_multi'), this.clickClone.bind(this))
$click($id('tool_delete'), this.deleteSelected.bind(this))
$click($id('tool_delete_multi'), this.deleteSelected.bind(this))
$click($id('tool_move_top'), this.moveToTopSelected.bind(this))
$click($id('tool_move_bottom'), this.moveToBottomSelected.bind(this))
$click($id('tool_topath'), this.convertToPath.bind(this))
$click($id('tool_make_link'), this.makeHyperlink.bind(this))
$click($id('tool_make_link_multi'), this.makeHyperlink.bind(this))
$click($id('tool_reorient'), this.reorientPath.bind(this))
$click($id('tool_group_elements'), this.clickGroup.bind(this))
$id('tool_position').addEventListener('change', (evt) => this.clickAlignEle.bind(this)(evt))
$click($id('tool_align_left'), () => this.clickAlign.bind(this)('left'))
$click($id('tool_align_right'), () => this.clickAlign.bind(this)('right'))
$click($id('tool_align_center'), () => this.clickAlign.bind(this)('center'))
$click($id('tool_align_top'), () => this.clickAlign.bind(this)('top'))
$click($id('tool_align_bottom'), () => this.clickAlign.bind(this)('bottom'))
$click($id('tool_align_middle'), () => this.clickAlign.bind(this)('middle'))
$click($id('tool_align_distrib_horiz'), () => this.clickAlign.bind(this)('distrib_horiz'))
$click($id('tool_align_distrib_verti'), () => this.clickAlign.bind(this)('distrib_verti'))
$click($id('tool_node_clone'), this.clonePathNode.bind(this))
$click($id('tool_node_delete'), this.deletePathNode.bind(this))
$click($id('tool_openclose_path'), this.opencloseSubPath.bind(this))
$click($id('tool_add_subpath'), this.addSubPath.bind(this))
$click($id('tool_node_link'), 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))
$click($id('tool_ungroup'), this.clickGroup.bind(this))
$click($id('tool_bold'), this.clickBold.bind(this))
$click($id('tool_italic'), this.clickItalic.bind(this))
$click($id('tool_text_decoration_underline'), () => this.clickTextDecoration.bind(this)('underline'))
$click($id('tool_text_decoration_linethrough'), () => this.clickTextDecoration.bind(this)('line-through'))
$click($id('tool_text_decoration_overline'), () => this.clickTextDecoration.bind(this)('overline'))
$id('tool_text_anchor').addEventListener('change', (evt) => this.clickTextAnchor.bind(this)(evt))
$id('tool_letter_spacing').addEventListener('change', this.changeLetterSpacing.bind(this))
$id('tool_word_spacing').addEventListener('change', this.changeWordSpacing.bind(this))
$id('tool_text_length').addEventListener('change', this.changeTextLength.bind(this))
$id('tool_length_adjust').addEventListener('change', (evt) => this.changeLengthAdjust.bind(this)(evt))
$click($id('tool_unlink_use'), this.clickGroup.bind(this))
$id('image_url').addEventListener('change', (evt) => { this.setImageURL(evt.currentTarget.value) });
// all top panel attributes
[
'elem_id',
'elem_class',
'circle_cx',
'circle_cy',
'circle_r',
'ellipse_cx',
'ellipse_cy',
'ellipse_rx',
'ellipse_ry',
'selected_x',
'selected_y',
'rect_width',
'rect_height',
'line_x1',
'line_x2',
'line_y1',
'line_y2',
'image_width',
'image_height',
'path_node_x',
'path_node_y'
].forEach(attrId =>
$id(attrId).addEventListener('change', this.attrChanger.bind(this))
)
}
}
export default TopPanel