#86 Jquery convert to JavaScript (#88)

This commit is contained in:
Agriya Dev5
2021-04-17 01:52:39 +05:30
committed by GitHub
parent a493dad418
commit 600ae92db5
435 changed files with 2728 additions and 10930 deletions

View File

@@ -166,7 +166,8 @@ export default class ConfigObj {
'ext-eyedropper',
'ext-grid',
'ext-imagelib',
'ext-markers',
// 'ext-arrows',
// 'ext-markers',
'ext-overview_window',
'ext-panning',
'ext-polygon',

View File

@@ -37,6 +37,33 @@ import MainMenu from './MainMenu.js';
const {$id, $qa, isNullish, encode64, decode64, blankPageObjectURL} = SvgCanvas;
/** A storage solution aimed at replacing jQuerys data function.
* Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap].
* This makes sure the data is garbage collected when the node is removed.
*/
window.dataStorage = {
_storage: new WeakMap(),
put: function (element, key, obj) {
if (!this._storage.has(element)) {
this._storage.set(element, new Map());
}
this._storage.get(element).set(key, obj);
},
get: function (element, key) {
return this._storage.get(element).get(key);
},
has: function (element, key) {
return this._storage.has(element) && this._storage.get(element).has(key);
},
remove: function (element, key) {
var ret = this._storage.get(element).delete(key);
if (!this._storage.get(element).size === 0) {
this._storage.delete(element);
}
return ret;
}
}
/**
*
*/
@@ -293,20 +320,41 @@ class Editor extends EditorStartup {
evt.preventDefault();
});
}
// parents() https://stackoverflow.com/a/12981248
getParents(el, parentSelector /* optional */) {
// If no parentSelector defined will bubble up all the way to *document*
if (parentSelector === undefined) {
parentSelector = document;
}
var parents = [];
var p = el.parentNode;
while (p !== parentSelector) {
var o = p;
parents.push(o);
p = o.parentNode;
}
parents.push(parentSelector); // Push that parentSelector you wanted to stop at
return parents;
}
/**
* @returns {void}
*/
setTitles () {
// Tooltips not directly associated with a single function
const keyAssocs = {
'4/Shift+4': '#tools_rect',
'5/Shift+5': '#tools_ellipse'
'4/Shift+4': 'tools_rect',
'5/Shift+5': 'tools_ellipse'
};
Object.entries(keyAssocs).forEach(([keyval, sel]) => {
const menu = ($(sel).parents('#main_menu').length);
const parentsElements = this.getParents($id(sel), $id('main_menu'))
const menu = (parentsElements.length);
$qa(sel).forEach((element) => {
const t = (menu) ? $(element).text().split(' [')[0] : element.title.split(' [')[0];
const t = (menu) ? element.textContent.split(' [')[0] : element.title.split(' [')[0];
let keyStr = '';
// Shift+Up
keyval.split('/').forEach((key, i) => {
@@ -427,7 +475,7 @@ class Editor extends EditorStartup {
// regular URL
this.svgCanvas.embedImage(url, function (dataURI) {
// Couldn't embed, so show warning
$('#url_notice').toggle(!dataURI);
$id('url_notice').style.display = (!dataURI) ? 'block' : 'none';
this.defaultImageURL = url;
});
$id("image_url").style.display = 'block';
@@ -559,7 +607,7 @@ class Editor extends EditorStartup {
// if (this.curContext) {
// new_title = new_title + this.curContext;
// }
$('title:first').text(newTitle);
document.querySelector('title').textContent = newTitle;
}
// called when we've selected a different element
@@ -707,9 +755,7 @@ class Editor extends EditorStartup {
*/
zoomChanged (win, bbox, autoCenter) {
const scrbar = 15,
// res = this.svgCanvas.getResolution(), // Currently unused
wArea = this.workarea;
// const canvasPos = $('#svgcanvas').position(); // Currently unused
const zInfo = this.svgCanvas.setBBoxZoom(bbox, parseFloat(getComputedStyle(wArea, null).width.replace("px", "")) - scrbar, parseFloat(getComputedStyle(wArea, null).height.replace("px", "")) - scrbar);
if (!zInfo) { return; }
const zoomlevel = zInfo.zoom,
@@ -750,11 +796,11 @@ class Editor extends EditorStartup {
if (context) {
let str = '';
linkStr = '<a href="#" data-root="y">' + this.svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>';
$(context).parentsUntil('#svgcontent > g').andSelf().each(() => {
if (this.id) {
str += ' > ' + this.id;
linkStr += (this !== context) ? ` > <a href="#">${this.id}</a>` : ` > ${this.id}`;
const parentsUntil = getParentsUntil(context, '#svgcontent > g');
parentsUntil.forEach(function (parent) {
if (parent.id) {
str += ' > ' + parent.id;
linkStr += (parent !== context) ? ` > <a href="#">${parent.id}</a>` : ` > ${parent.id}`;
}
});
@@ -762,7 +808,9 @@ class Editor extends EditorStartup {
} else {
this.curContext = null;
}
$('#cur_context_panel').toggle(Boolean(context)).html(linkStr);
$id('cur_context_panel').style.display = (Boolean(context)) ? 'block' : 'none';
// eslint-disable-next-line no-unsanitized/property
$id('cur_context_panel').innerHTML = linkStr;
this.updateTitle();
}
@@ -775,13 +823,18 @@ class Editor extends EditorStartup {
*/
setIcon (elem, iconId) {
// eslint-disable-next-line max-len
const icon = (typeof iconId === 'string') ? $('<img src="' + this.configObj.curConfig.imgPath + iconId + '">') : iconId.clone();
const img = document.createElement("img");
img.src = this.configObj.curConfig.imgPath + iconId;
const icon = (typeof iconId === 'string') ? img : iconId.cloneNode(true);
if (!icon) {
// Todo: Investigate why this still occurs in some cases
console.log('NOTE: Icon image missing: ' + iconId);
return;
}
$(elem).empty().append(icon);
// empty()
while($id(elem).firstChild)
$id(elem).removeChild($id(elem).firstChild);
$id(elem).appendChild(icon);
}
/**
@@ -817,55 +870,72 @@ class Editor extends EditorStartup {
};
if (ext.context_tools) {
$.each(ext.context_tools, function (i, tool) {
ext.context_tools.forEach(function(tool, i){
// Add select tool
const contId = tool.container_id ? (' id="' + tool.container_id + '"') : '';
let panel = $('#' + tool.panel);
let panel = $id(tool.panel);
// create the panel if it doesn't exist
if (!panel.length) {
panel = $('<div>', {id: tool.panel}).appendTo('#tools_top');
if (!panel) {
panel = document.createElement("div");
panel.id = tool.panel;
$id('tools_top').appendChild(panel);
}
let html;
// TODO: Allow support for other types, or adding to existing tool
switch (tool.type) {
case 'tool_button': {
html = '<div class="tool_button">' + tool.id + '</div>';
const div = $(html).appendTo(panel);
html = document.createElement("div");
html.className = "tool_button";
html.textContent = tool.id
panel.appendChild(html);
if (tool.events) {
$.each(tool.events, function (evt, func) {
$(div).bind(evt, func);
tool.events.forEach((func, evt) => {
html.addEventListener(evt, func);
});
}
break;
} case 'select': {
html = '<label' + contId + '>' +
'<select id="' + tool.id + '">';
$.each(tool.options, function (val, text) {
label = document.createElement("label");
if (tool.container_id) {
label.id = tool.container_id;
}
html = '<select id="' + tool.id + '">';
tool.options.forEach((text, val) => {
const sel = (val === tool.defval) ? ' selected' : '';
html += '<option value="' + val + '"' + sel + '>' + text + '</option>';
});
html += '</select></label>';
html += '</select>';
// eslint-disable-next-line no-unsanitized/property
label.innerHTML = html;
// Creates the tool, hides & adds it, returns the select element
const sel = $(html).appendTo(panel).find('select');
panel.appendChild(label);
$.each(tool.events, function (evt, func) {
$(sel).bind(evt, func);
const sel = label.querySelector('select');
tool.events.forEach((func, evt) => {
sel.addEventListener(evt, func);
});
break;
} case 'button-select': {
html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' +
'<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>';
const div = document.createElement("div");
div.id = tool.id;
div.className = "dropdown toolset";
div.title = tool.title;
// eslint-disable-next-line no-unsanitized/property
div.innerHTML = '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button>';
const list = $('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists');
const list = document.createElement("ul");
list.id = tool.id;
if($id('option_lists')) $id('option_lists').appendChild(list);
if (tool.colnum) {
list.addClass('optcols' + tool.colnum);
list.className = ('optcols' + tool.colnum);
}
panel.appendChild(div);
// Creates the tool, hides & adds it, returns the select element
/* const dropdown = */ $(html).appendTo(panel).children();
btnSelects.push({
elem: ('#' + tool.id),
@@ -877,25 +947,30 @@ class Editor extends EditorStartup {
break;
} case 'input': {
html = '<label' + contId + '>' +
'<span id="' + tool.id + '_label">' +
const html = document.createElement("label");
if(tool.container_id) { html.id = tool.container_id; }
html.innerHTML
// eslint-disable-next-line no-unsanitized/property
html.innerHTML = '<span id="' + tool.id + '_label">' +
tool.label + ':</span>' +
'<input id="' + tool.id + '" title="' + tool.title +
'" size="' + (tool.size || '4') +
'" value="' + (tool.defval || '') + '" type="text"/></label>';
'" value="' + (tool.defval || '') + '" type="text"/>';
// Creates the tool, hides & adds it, returns the select element
// Add to given tool.panel
const inp = $(html).appendTo(panel).find('input');
panel.appendChild(html);
const inp = html.querySelector('input');
if (tool.spindata) {
inp.SpinButton(tool.spindata);
}
if (tool.events) {
$.each(tool.events, function (evt, func) {
inp.bind(evt, func);
if ( tool?.events !== undefined ) {
Object.entries(tool.events).forEach((entry) => {
const [evt, func] = entry;
inp.addEventListener(evt, func);
});
}
break;
@@ -911,11 +986,6 @@ class Editor extends EditorStartup {
return runCallback();
}
/*
this.addDropDown('#font_family_dropdown', () => {
$('#font_family').val($(this).text()).change();
});
*/
/**
* @param {Float} multiplier
* @returns {void}
@@ -1166,7 +1236,7 @@ class Editor extends EditorStartup {
// const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
const oldLayerName = $('#layerlist tr.layersel td.layername').text();
const oldLayerName = ($id('#layerlist')) ? $id('#layerlist').querySelector('tr.layersel td.layername').textContent : "";
const renameLayer = (oldLayerName === this.uiStrings.common.layer + ' 1');
this.svgCanvas.setUiStrings(allStrings);
@@ -1186,14 +1256,28 @@ class Editor extends EditorStartup {
'#linejoin_miter': '#cur_linejoin',
'#linecap_butt': '#cur_linecap'
};
$.each(this.elems, function (source, dest) {
$(dest).attr('title', $(source)[0].title);
});
for (const [source, dest] of Object.entries(this.elems)) {
if(dest === '#tool_stroke .color_block'){
if($id('tool_stroke')) {
$id('tool_stroke').querySelector('.color_block').setAttribute('title', $id(source).title);
}
} else if(dest === '#tool_fill label, #tool_fill .color_block'){
if($id('tool_fill') && $id('tool_fill').querySelector('.color_block')) {
$id('tool_fill').querySelector('label').setAttribute('title', $id(source).title);
console.log($id('tool_fill').querySelector('.color_block'));
$id('tool_fill').querySelector('.color_block').setAttribute('title', $id(source).title);
}
} else {
if ($id(dest)) {
$id(dest).setAttribute('title', $id(source).title);
}
}
}
// Copy alignment titles
$('#multiselected_panel div[id^=tool_align]').each(() => {
$('#tool_pos' + this.id.substr(10))[0].title = this.title;
const selElements = $id('multiselected_panel').querySelectorAll('div[id^=tool_align]');
Array.from(selElements).forEach(function(element) {
$id('tool_pos' + element.id.substr(10)).title = element.title;
});
}

View File

@@ -131,16 +131,21 @@ class EditorStartup {
this.selectedElement = null;
this.multiselected = false;
$('#cur_context_panel').delegate('a', 'click', (evt) => {
const link = $(evt.currentTarget);
if (link.attr('data-root')) {
this.svgCanvas.leaveContext();
} else {
this.svgCanvas.setContext(link.text());
}
this.svgCanvas.clearSelection();
return false;
});
const aLinks = $id('cur_context_panel').querySelectorAll('a')
for (const aLink of aLinks) {
aLink.addEventListener('click', (evt) => {
const link = evt.currentTarget;
if (link.hasAttribute('data-root')) {
this.svgCanvas.leaveContext();
} else {
this.svgCanvas.setContext(link.textContent);
}
this.svgCanvas.clearSelection();
return false;
});
}
// bind the selected event to our function that handles updates to the UI
this.svgCanvas.bind('selected', this.selectedChanged.bind(this));
this.svgCanvas.bind('transition', this.elementTransition.bind(this));
@@ -178,7 +183,7 @@ class EditorStartup {
);
this.svgCanvas.bind('contextset', this.contextChanged.bind(this));
this.svgCanvas.bind('extension_added', this.extAdded.bind(this));
this.svgCanvas.textActions.setInputElem($('#text')[0]);
this.svgCanvas.textActions.setInputElem($id('text'));
this.setBackground(this.configObj.pref('bkgd_color'), this.configObj.pref('bkgd_url'));
@@ -195,7 +200,12 @@ class EditorStartup {
$id('se-img-prop').setAttribute('save', this.configObj.pref('img_save'));
// Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
$('select').change((evt) => { $(evt.currentTarget).blur(); });
const selElements = document.querySelectorAll("select");
Array.from(selElements).forEach(function(element) {
element.addEventListener('change', function(evt) {
evt.currentTarget.blur();
});
});
// fired when user wants to move elements to another layer
let promptMoveLayerOnce = false;
@@ -233,8 +243,15 @@ class EditorStartup {
self.svgCanvas.setSegType(evt.currentTarget.value);
});
$('#text').bind('keyup input', (evt) => {
this.svgCanvas.setTextContent(evt.currentTarget.value);
function addListenerMulti(element, eventNames, listener) {
var events = eventNames.split(' ');
for (var i=0, iLen=events.length; i<iLen; i++) {
element.addEventListener(events[i], listener, false);
}
}
addListenerMulti($id('text'), 'keyup input', function(evt){
self.svgCanvas.setTextContent(evt.currentTarget.value);
});
$id('image_url').addEventListener('change', function(evt) {
self.setImageURL(evt.currentTarget.value);
@@ -257,7 +274,7 @@ class EditorStartup {
let lastX = null, lastY = null,
panning = false, keypan = false;
$('#svgcanvas').bind('mousemove mouseup', function (evt) {
$id('svgcanvas').addEventListener('mouseup', function(evt) {
if (panning === false) { return true; }
wArea.scrollLeft -= (evt.clientX - lastX);
@@ -268,7 +285,20 @@ class EditorStartup {
if (evt.type === 'mouseup') { panning = false; }
return false;
}).mousedown(function (evt) {
});
$id('svgcanvas').addEventListener('mousemove', function(evt) {
if (panning === false) { return true; }
wArea.scrollLeft -= (evt.clientX - lastX);
wArea.scrollTop -= (evt.clientY - lastY);
lastX = evt.clientX;
lastY = evt.clientY;
if (evt.type === 'mouseup') { panning = false; }
return false;
});
$id('svgcanvas').addEventListener('mousedown', function(evt) {
if (evt.button === 1 || keypan === true) {
panning = true;
lastX = evt.clientX;
@@ -278,7 +308,7 @@ class EditorStartup {
return true;
});
$(window).mouseup(() => {
window.addEventListener('mouseup', function(evt) {
panning = false;
});
@@ -323,20 +353,24 @@ class EditorStartup {
* @returns {void}
*/
const unfocus = () => {
$(inp).blur();
inp.blur();
};
$('#svg_editor').find('button, select, input:not(#text)').focus(() => {
inp = this;
this.uiContext = 'toolbars';
this.workarea.addEventListener('mousedown', unfocus);
}).blur(() => {
this.uiContext = 'canvas';
this.workarea.removeEventListener('mousedown', unfocus);
// Go back to selecting text if in textedit mode
if (this.svgCanvas.getMode() === 'textedit') {
$('#text').focus();
}
const liElems = document.getElementById('svg_editor').querySelectorAll('button, select, input:not(#text)');
Array.prototype.forEach.call(liElems, function(el, i){
el.addEventListener("focus", (e) => {
inp = e.currentTarget;
this.uiContext = 'toolbars';
this.workarea.addEventListener('mousedown', unfocus);
});
el.addEventListener("blur", () => {
this.uiContext = 'canvas';
this.workarea.removeEventListener('mousedown', unfocus);
// Go back to selecting text if in textedit mode
if (this.svgCanvas.getMode() === 'textedit') {
$id('text').focus();
}
});
});
// ref: https://stackoverflow.com/a/1038781
function getWidth() {
@@ -365,7 +399,7 @@ class EditorStartup {
window.addEventListener('resize', (evt) => {
Object.entries(winWh).forEach(([type, val]) => {
const curval = $(window)[type]();
const curval = (type === 'width') ? window.innerWidth - 15 : window.innerHeight;
this.workarea['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
winWh[type] = curval;
});
@@ -376,7 +410,7 @@ class EditorStartup {
this.rulers.manageScroll();
});
$('#url_notice').click(() => {
$id('url_notice').addEventListener('click', () => {
seAlert(this.title);
});
@@ -407,10 +441,17 @@ class EditorStartup {
this.workarea.style.lineHeight = this.workarea.style.height;
};
$(window).bind('load resize', centerCanvas);
addListenerMulti(window, 'load resize', centerCanvas);
// Prevent browser from erroneously repopulating fields
$('input,select').attr('autocomplete', 'off');
const inputEles = document.querySelectorAll('input');
Array.from(inputEles).forEach(function(inputEle) {
inputEle.setAttribute('autocomplete', 'off');
});
const selectEles = document.querySelectorAll('select');
Array.from(selectEles).forEach(function(inputEle) {
inputEle.setAttribute('autocomplete', 'off');
});
$id('se-svg-editor-dialog').addEventListener('change', function (e) {
if (e?.detail?.copy === 'click') {
@@ -456,7 +497,7 @@ class EditorStartup {
this.moveUpDownSelected('Down');
break;
case 'move_back':
this.svgCanvas.moveToBottomSelected();
this.svgCanvas.moveToBottomSelectedElement();
break;
default:
if (hasCustomHandler(action)) {
@@ -485,7 +526,7 @@ class EditorStartup {
$id('tool_wireframe').click();
}
$('#rulers').toggle(Boolean(this.configObj.curConfig.showRulers));
$id('rulers').style.display = (Boolean(this.configObj.curConfig.showRulers)) ? 'block' : 'none';
if (this.configObj.curConfig.showRulers) {
$editDialog.setAttribute('showrulers', true);
@@ -625,8 +666,10 @@ class EditorStartup {
this.workarea.addEventListener('dragover', this.onDragOver);
this.workarea.addEventListener('dragleave', this.onDragLeave);
this.workarea.addEventListener('drop', importImage);
const imgImport = $('<input type="file">').change(importImage);
$(window).on('importImages', () => imgImport.click());
const imgImport = document.createElement('input');
imgImport.type="file";
imgImport.addEventListener('change', importImage);
window.addEventListener('importImages', () => imgImport.click());
}
this.updateCanvas(true);

View File

@@ -1,4 +1,3 @@
/* globals $ */
import SvgCanvas from "../svgcanvas/svgcanvas.js";
import {convertUnit, isValidUnit} from '../common/units.js';
import {isChrome} from '../common/browser.js';

View File

@@ -1,4 +1,3 @@
/* globals $ */
import {getTypeMap} from '../common/units.js';
import rulersTemplate from './templates/rulersTemplate.js';
/**
@@ -53,14 +52,15 @@ class Rulers {
const dim = isX ? 'x' : 'y';
const lentype = isX ? 'width' : 'height';
const contentDim = Number(contentElem.getAttribute(dim));
const $hcanvOrig = $('#ruler_' + dim + ' canvas:first');
const {$id} = this.svgCanvas;
const $hcanvOrig = $id('ruler_' + dim).querySelector('canvas');
// Bit of a hack to fully clear the canvas in Safari & IE9
const $hcanv = $hcanvOrig.clone();
const $hcanv = $hcanvOrig.cloneNode(true);
// eslint-disable-next-line no-unsanitized/property
$hcanvOrig.replaceWith($hcanv);
const hcanv = $hcanv[0];
const hcanv = $hcanv;
// Set the canvas size to the width of the container
let rulerLen;
@@ -78,7 +78,12 @@ class Rulers {
ctx.fillRect(0, 0, hcanv.width, hcanv.height);
// Remove any existing canvasses
$hcanv.siblings().remove();
const elements = Array.prototype.filter.call($hcanv.parentNode.children, function(child){
return child !== $hcanv;
});
Array.from(elements).forEach(function(element) {
element.remove();
});
// Create multiple canvases when necessary (due to browser limits)
if (rulerLen >= limit) {

View File

@@ -2,7 +2,7 @@
* @param {any} obj
* @returns {any}
*/
export function findPos (obj) {
export function findPos(obj) {
let curleft = 0;
let curtop = 0;
if (obj.offsetParent) {
@@ -10,9 +10,9 @@ export function findPos (obj) {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return {left: curleft, top: curtop};
return { left: curleft, top: curtop };
}
return {left: curleft, top: curtop};
return { left: curleft, top: curtop };
}
export function isObject(item) {
@@ -34,4 +34,184 @@ export function mergeDeep(target, source) {
});
}
return output;
}
}
/**
* Get the closest matching element up the DOM tree.
* @param {Element} elem Starting element
* @param {String} selector Selector to match against (class, ID, data attribute, or tag)
* @return {Boolean|Element} Returns null if not match found
*/
export function getClosest(elem, selector) {
const firstChar = selector.charAt(0);
const supports = 'classList' in document.documentElement;
let attribute, value;
// If selector is a data attribute, split attribute from value
if (firstChar === '[') {
selector = selector.substr(1, selector.length - 2);
attribute = selector.split('=');
if (attribute.length > 1) {
value = true;
attribute[1] = attribute[1].replace(/"/g, '').replace(/'/g, '');
}
}
// Get closest match
for (; elem && elem !== document && elem.nodeType === 1; elem = elem.parentNode) {
// If selector is a class
if (firstChar === '.') {
if (supports) {
if (elem.classList.contains(selector.substr(1))) {
return elem;
}
} else {
if (new RegExp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test(elem.className)) {
return elem;
}
}
}
// If selector is an ID
if (firstChar === '#') {
if (elem.id === selector.substr(1)) {
return elem;
}
}
// If selector is a data attribute
if (firstChar === '[') {
if (elem.hasAttribute(attribute[0])) {
if (value) {
if (elem.getAttribute(attribute[0]) === attribute[1]) {
return elem;
}
} else {
return elem;
}
}
}
// If selector is a tag
if (elem.tagName.toLowerCase() === selector) {
return elem;
}
}
return null;
};
/**
* Get all DOM element up the tree that contain a class, ID, or data attribute
* @param {Node} elem The base element
* @param {String} selector The class, id, data attribute, or tag to look for
* @return {Array} Null if no match
*/
export function getParents(elem, selector) {
const parents = [];
let firstChar;
if ( selector ) {
firstChar = selector.charAt(0);
}
// Get matches
for ( ; elem && elem !== document; elem = elem.parentNode ) {
if ( selector ) {
// If selector is a class
if ( firstChar === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
parents.push( elem );
}
}
// If selector is an ID
if ( firstChar === '#' ) {
if ( elem.id === selector.substr(1) ) {
parents.push( elem );
}
}
// If selector is a data attribute
if ( firstChar === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 1) ) ) {
parents.push( elem );
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
parents.push( elem );
}
} else {
parents.push( elem );
}
}
// Return parents if any exist
if ( parents.length === 0 ) {
return null;
} else {
return parents;
}
};
export function getParentsUntil(elem, parent, selector) {
let parents = [];
let parentType;
let selectorType;
if ( parent ) {
parentType = parent.charAt(0);
}
if ( selector ) {
selectorType = selector.charAt(0);
}
// Get matches
for ( ; elem && elem !== document; elem = elem.parentNode ) {
// Check if parent has been reached
if ( parent ) {
// If parent is a class
if ( parentType === '.' ) {
if ( elem.classList.contains( parent.substr(1) ) ) {
break;
}
}
// If parent is an ID
if ( parentType === '#' ) {
if ( elem.id === parent.substr(1) ) {
break;
}
}
// If parent is a data attribute
if ( parentType === '[' ) {
if ( elem.hasAttribute( parent.substr(1, parent.length - 1) ) ) {
break;
}
}
// If parent is a tag
if ( elem.tagName.toLowerCase() === parent ) {
break;
}
}
if ( selector ) {
// If selector is a class
if ( selectorType === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
parents.push( elem );
}
}
// If selector is an ID
if ( selectorType === '#' ) {
if ( elem.id === selector.substr(1) ) {
parents.push( elem );
}
}
// If selector is a data attribute
if ( selectorType === '[' ) {
if ( elem.hasAttribute( selector.substr(1, selector.length - 1) ) ) {
parents.push( elem );
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
parents.push( elem );
}
} else {
parents.push( elem );
}
}
// Return parents if any exist
if ( parents.length === 0 ) {
return null;
} else {
return parents;
}
};

View File

@@ -223,7 +223,6 @@ export function jGraduateMethod (elem, options, okCallback, cancelCallback) {
idref = '#' + $this.getAttribute('id') + ' ';
// JFH !!!!!
const $shadowRoot = elem.parentNode;
// const $wc = (selector) => $($shadowRoot.querySelectorAll(selector));
if (!idref) {
// eslint-disable-next-line no-alert

View File

@@ -134,45 +134,3 @@ export class SEPalette extends HTMLElement {
// Register
customElements.define('se-palette', SEPalette);
/* #palette_holder {
overflow: hidden;
margin-top: 5px;
padding: 5px;
position: absolute;
right: 15px;
height: 16px;
background: #f0f0f0;
border-radius: 3px;
z-index: 2;
#palette {
float: left;
width: 632px;
height: 16px;
}
$('.palette_item').mousedown(function (evt) {
// shift key or right click for stroke
const picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';
let color = $(this).data('rgb');
let paint;
// Webkit-based browsers returned 'initial' here for no stroke
if (color === 'none' || color === 'transparent' || color === 'initial') {
color = 'none';
paint = new $.jGraduate.Paint();
} else {
paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)});
}
paintBox[picker].setPaint(paint);
svgCanvas.setColor(picker, color);
if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) {
svgCanvas.setPaintOpacity(picker, 1.0);
}
updateToolButtonState();
}).bind('contextmenu', function (e) { e.preventDefault(); });
*/

View File

@@ -98,14 +98,17 @@ function exportPDF () {
const frameBase = 'https://raw.githack.com/SVG-Edit/svgedit/master';
// const frameBase = 'http://localhost:8001';
const framePath = '/editor/xdomain-svg-editor-es.html?extensions=ext-xdomain-messaging.js';
const iframe = $('<iframe width="900px" height="600px" id="svgedit" src="javascript:0"></iframe>');
iframe[0].src = frameBase + framePath +
const iframe = document.createElement('iframe');
iframe.id = "svgedit";
iframe.style.width = "900px";
iframe.style.width = "600px";
iframe.src = frameBase + framePath +
(location.href.includes('?')
// ? location.href.replace(/\?(?<search>.*)$/, '&$<search>')
? location.href.replace(/\?(.*)$/, '&$1')
: ''); // Append arguments to this file onto the iframe
iframe[0].addEventListener('load', function () {
iframe.addEventListener('load', function () {
svgCanvas = new EmbeddedSVGEdit(frame, [new URL(frameBase).origin]);
// Hide main button, as we will be controlling new, load, save, etc. from the host document
let doc;
@@ -121,10 +124,10 @@ iframe[0].addEventListener('load', function () {
}
// Add event handlers now that `svgCanvas` is ready
$('#load').click(loadSvg);
$('#save').click(saveSvg);
$('#exportPNG').click(exportPNG);
$('#exportPDF').click(exportPDF);
$id('load').addEventListener('click', loadSvg);
$id('save').addEventListener('click', saveSvg);
$id('exportPNG').addEventListener('click', exportPNG);
$id('exportPDF').addEventListener('click', exportPDF);
});
$('body').append(iframe);
document.body.appendChild(iframe);
const frame = document.getElementById('svgedit');

View File

@@ -89,7 +89,7 @@ export default {
* @returns {void}
*/
function showPanel (on) {
$('#arrow_panel').toggle(on);
$id('arrow_panel').style.display = (on) ? 'block' : 'none';
if (on) {
const el = selElems[0];
const end = el.getAttribute('marker-end');
@@ -219,21 +219,22 @@ export default {
const marker = getLinked(elem, 'marker-' + type);
if (!marker) { return; }
const curColor = $(marker).children().attr('fill');
const curD = $(marker).children().attr('d');
const curColor = marker.children.getAttribute('fill');
const curD = marker.children.getAttribute('d');
if (curColor === color) { return; }
const allMarkers = $(defs).find('marker');
const allMarkers = defs.querySelectorAll('marker');
let newMarker = null;
// Different color, check if already made
allMarkers.each(function () {
const attrs = $(this).children().attr(['fill', 'd']);
if (attrs.fill === color && attrs.d === curD) {
Array.from(allMarkers).forEach(function(marker) {
const attrsFill = marker.children.getAttribute('fill');
const attrsD = marker.children.getAttribute('d');
if (attrsFill === color && attrsD === curD) {
// Found another marker with this color and this path
newMarker = this;
newMarker = marker;
}
});
if (!newMarker) {
// Create a new marker with this color
const lastId = marker.id;
@@ -241,17 +242,17 @@ export default {
newMarker = addMarker(dir, type, arrowprefix + dir + allMarkers.length);
$(newMarker).children().attr('fill', color);
newMarker.children.setAttribute('fill', color);
}
$(elem).attr('marker-' + type, 'url(#' + newMarker.id + ')');
elem.setAttribute('marker-' + type, 'url(#' + newMarker.id + ')');
// Check if last marker can be removed
let remove = true;
$(S.svgcontent).find('line, polyline, path, polygon').each(function () {
const element = this;
$.each(mtypes, function (j, mtype) {
if ($(element).attr('marker-' + mtype) === 'url(#' + marker.id + ')') {
const sElements = S.svgcontent.querySelectorAll('line, polyline, path, polygon');
Array.prototype.forEach.call(sElements, function(element, i){
mtypes.forEach(function(mtype, j){
if (element.getAttribute('marker-' + mtype) === 'url(#' + marker.id + ')') {
remove = false;
return remove;
}
@@ -263,7 +264,7 @@ export default {
// Not found, so can safely remove
if (remove) {
$(marker).remove();
marker.remove();
}
});
}
@@ -289,7 +290,7 @@ export default {
$id("arrow_panel").style.display = 'none';
// Set ID so it can be translated in locale file
$('#arrow_list option')[0].id = 'connector_no_arrow';
$id('arrow_list option').setAttribute('id', 'connector_no_arrow');
},
async addLangData ({lang, importLocale}) {
const {langList} = await importLocale();

View File

@@ -38,7 +38,7 @@ export default {
$id("showbutton").style.display = 'block';
};
const showPanel = function (on) {
$('#closepath_panel').toggle(on);
$id('closepath_panel').style.display = (on) ? 'block' : 'none';
if (on) {
const path = selElems[0];
if (path) { updateButton(path); }

View File

@@ -27,8 +27,7 @@ export default {
const {getElem} = svgCanvas;
const {$, svgroot} = S,
addElem = svgCanvas.addSVGElementFromJson,
selManager = S.selectorManager,
elData = $.data;
selManager = S.selectorManager;
let startX,
startY,
@@ -88,7 +87,6 @@ export default {
*/
function getOffset (side, line) {
const giveOffset = line.getAttribute('marker-' + side);
// const giveOffset = $(line).data(side+'_off');
// TODO: Make this number (5) be based on marker width/height
const size = line.getAttribute('stroke-width') * 5;
@@ -100,12 +98,14 @@ export default {
* @returns {void}
*/
function showPanel (on) {
let connRules = $('#connector_rules');
if (!connRules.length) {
connRules = $('<style id="connector_rules"></style>').appendTo('head');
let connRules = $id('connector_rules');
if (!connRules) {
connRules = document.createElement('style');
connRules.setAttribute('id', 'connector_rules');
document.getElementsByTagName("head")[0].appendChild(connRules);
}
connRules.text(!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }');
$('#connector_panel').toggle(on);
connRules.textContent = (!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }');
$id('connector_panel').style.display = (on) ? 'block' : 'none';
}
/**
@@ -161,24 +161,24 @@ export default {
// const sw = line.getAttribute('stroke-width') * 5;
// Update bbox for this element
const bb = elData(line, pre + '_bb');
const bb = dataStorage.get(line, pre + '_bb');
bb.x = conn.start_x + diffX;
bb.y = conn.start_y + diffY;
elData(line, pre + '_bb', bb);
dataStorage.put(line, pre + '_bb', bb);
const altPre = conn.is_start ? 'end' : 'start';
// Get center pt of connected element
const bb2 = elData(line, altPre + '_bb');
const bb2 = dataStorage.get(line, altPre + '_bb');
const srcX = bb2.x + bb2.width / 2;
const srcY = bb2.y + bb2.height / 2;
// Set point of element being moved
const pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0
const pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line));
setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
// Set point of connected element
const pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line));
const pt2 = getBBintersect(pt.x, pt.y, dataStorage.get(line, altPre + '_bb'), getOffset(altPre, line));
setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
}
}
@@ -189,54 +189,50 @@ export default {
* @returns {void}
*/
function findConnectors (elems = selElems) {
const connectors = $(svgcontent).find('.se_connector');
// const connectors = svgcontent.querySelectorAll('.se_connector');
const connectors = svgcontent.querySelectorAll('.se_connector');
connections = [];
// Loop through connectors to see if one is connected to the element
connectors.each(function () {
Array.prototype.forEach.call(connectors, function(ethis, i){
let addThis;
/**
*
* @returns {void}
*/
function add () {
if (elems.includes(this)) {
// Pretend this element is selected
addThis = true;
}
}
// Grab the ends
const parts = [];
['start', 'end'].forEach(function (pos, i) {
const key = 'c_' + pos;
let part = elData(this, key);
let part = dataStorage.get(ethis, key);
if (part === null || part === undefined) { // Does this ever return nullish values?
part = document.getElementById(
this.attributes['se:connector'].value.split(' ')[i]
ethis.attributes['se:connector'].value.split(' ')[i]
);
elData(this, 'c_' + pos, part.id);
elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part]));
dataStorage.put(ethis, 'c_' + pos, part.id);
dataStorage.put(ethis, pos + '_bb', svgCanvas.getStrokedBBox([part]));
} else part = document.getElementById(part);
parts.push(part);
}, this);
}, ethis);
for (let i = 0; i < 2; i++) {
const cElem = parts[i];
addThis = false;
// The connected element might be part of a selected group
$(cElem).parents().each(add);
parents = svgCanvas.getParents(cElem.parentNode);
Array.prototype.forEach.call(parents, function(el, i){
if (elems.includes(el)) {
// Pretend this element is selected
addThis = true;
}
});
if (!cElem || !cElem.parentNode) {
$(this).remove();
ethis.remove();
continue;
}
if (elems.includes(cElem) || addThis) {
const bb = svgCanvas.getStrokedBBox([cElem]);
connections.push({
elem: cElem,
connector: this,
connector: ethis,
is_start: (i === 0),
start_x: bb.x,
start_y: bb.y
@@ -270,13 +266,13 @@ export default {
const bb = svgCanvas.getStrokedBBox([elem]);
bb.x = conn.start_x;
bb.y = conn.start_y;
elData(line, pre + '_bb', bb);
/* const addOffset = */ elData(line, pre + '_off');
dataStorage.put(line, pre + '_bb', bb);
/* const addOffset = */ dataStorage.get(line, pre + '_off');
const altPre = conn.is_start ? 'end' : 'start';
// Get center pt of connected element
const bb2 = elData(line, altPre + '_bb');
const bb2 = dataStorage.get(line, altPre + '_bb');
const srcX = bb2.x + bb2.width / 2;
const srcY = bb2.y + bb2.height / 2;
@@ -285,7 +281,7 @@ export default {
setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
// Set point of connected element
const pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line));
const pt2 = getBBintersect(pt.x, pt.y, dataStorage.get(line, altPre + '_bb'), getOffset(altPre, line));
setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
// Update points attribute manually for webkit
@@ -308,7 +304,8 @@ export default {
const gse = svgCanvas.groupSelectedElements;
svgCanvas.groupSelectedElements = function (...args) {
svgCanvas.removeFromSelection($('.se_connector').toArray());
svgCanvas.removeFromSelection(document.querySelectorAll('.se_connector'));
return gse.apply(this, args);
};
@@ -329,17 +326,18 @@ export default {
*/
function init () {
// Make sure all connectors have data set
$(svgcontent).find('*').each(function () {
const conn = this.getAttributeNS(seNs, 'connector');
const elements = svgcontent.querySelectorAll('*');
elements.forEach(function (curthis) {
const conn = curthis.getAttributeNS(seNs, 'connector');
if (conn) {
this.setAttribute('class', 'se_connector');
curthis.setAttribute('class', 'se_connector');
const connData = conn.split(' ');
const sbb = svgCanvas.getStrokedBBox([getElem(connData[0])]);
const ebb = svgCanvas.getStrokedBBox([getElem(connData[1])]);
$(this).data('c_start', connData[0])
.data('c_end', connData[1])
.data('start_bb', sbb)
.data('end_bb', ebb);
dataStorage.put(curthis, 'c_start', connData[0]);
dataStorage.put(curthis, 'c_end', connData[1]);
dataStorage.put(curthis, 'start_bb', sbb);
dataStorage.put(curthis, 'end_bb', ebb);
svgCanvas.getEditorNS(true);
}
});
@@ -379,13 +377,13 @@ export default {
const mouseTarget = e.target;
const parents = $(mouseTarget).parents();
const parents = svgCanvas.getParents(mouseTarget.parentNode);
if ($.inArray(svgcontent, parents) !== -1) {
// Connectable element
// If child of foreignObject, use parent
const fo = $(mouseTarget).closest('foreignObject');
const fo = svgCanvas.getClosest(mouseTarget.parentNode, 'foreignObject');
startElem = fo.length ? fo[0] : mouseTarget;
// Get center of source element
@@ -408,7 +406,7 @@ export default {
style: 'pointer-events:none'
}
});
elData(curLine, 'start_bb', bb);
dataStorage.put(curLine, 'start_bb', bb);
}
return {
started: true
@@ -433,7 +431,7 @@ export default {
if (mode === 'connector' && started) {
// const sw = curLine.getAttribute('stroke-width') * 3;
// Set start point (adjusts based on bb)
const pt = getBBintersect(x, y, elData(curLine, 'start_bb'), getOffset('start', curLine));
const pt = getBBintersect(x, y, dataStorage.get(curLine, 'start_bb'), getOffset('start', curLine));
startX = pt.x;
startY = pt.y;
@@ -446,7 +444,7 @@ export default {
while (slen--) {
const elem = selElems[slen];
// Look for selected connector elements
if (elem && elData(elem, 'c_start')) {
if (elem && dataStorage.get(elem, 'c_start')) {
// Remove the "translate" transform given to move
svgCanvas.removeFromSelection([elem]);
svgCanvas.getTransformList(elem).clear();
@@ -467,10 +465,10 @@ export default {
if (svgCanvas.getMode() !== 'connector') {
return undefined;
}
const fo = $(mouseTarget).closest('foreignObject');
const fo = svgCanvas.getClosest(mouseTarget.parentNode, 'foreignObject');
if (fo.length) { mouseTarget = fo[0]; }
const parents = $(mouseTarget).parents();
const parents = svgCanvas.getParents(mouseTarget.parentNode);
if (mouseTarget === startElem) {
// Start line through click
@@ -481,9 +479,9 @@ export default {
started
};
}
if ($.inArray(svgcontent, parents) === -1) {
if (parents.indexOf(svgcontent) === -1) {
// Not a valid target element, so remove line
$(curLine).remove();
curLine.remove();
started = false;
return {
keep: false,
@@ -498,13 +496,13 @@ export default {
const connStr = startId + ' ' + endId;
const altStr = endId + ' ' + startId;
// Don't create connector if one already exists
const dupe = $(svgcontent).find('.se_connector').filter(function () {
const conn = this.getAttributeNS(seNs, 'connector');
const dupe = Array.prototype.filter.call(svgcontent.querySelectorAll('.se_connector'), function (aThis, i) {
const conn = aThis.getAttributeNS(seNs, 'connector');
if (conn === connStr || conn === altStr) { return true; }
return false;
});
if (dupe.length) {
$(curLine).remove();
curLine.remove();
return {
keep: false,
element: null,
@@ -516,10 +514,9 @@ export default {
const pt = getBBintersect(startX, startY, bb, getOffset('start', curLine));
setPoint(curLine, 'end', pt.x, pt.y, true);
$(curLine)
.data('c_start', startId)
.data('c_end', endId)
.data('end_bb', bb);
dataStorage.put(curLine, 'c_start', startId);
dataStorage.put(curLine, 'c_end', endId);
dataStorage.put(curLine, 'end_bb', bb);
seNs = svgCanvas.getEditorNS(true);
curLine.setAttributeNS(seNs, 'se:connector', connStr);
curLine.setAttribute('class', 'se_connector');
@@ -536,7 +533,7 @@ export default {
},
selectedChanged (opts) {
// TODO: Find better way to skip operations if no connectors are in use
if (!$(svgcontent).find('.se_connector').length) { return; }
if (!svgcontent.querySelectorAll('.se_connector').length) { return; }
if (svgCanvas.getMode() === 'connector') {
svgCanvas.setMode('select');
@@ -548,7 +545,7 @@ export default {
let i = selElems.length;
while (i--) {
const elem = selElems[i];
if (elem && elData(elem, 'c_start')) {
if (elem && dataStorage.get(elem, 'c_start')) {
selManager.requestSelector(elem).showGrips(false);
if (opts.selectedElement && !opts.multiselected) {
// TODO: Set up context tools and hide most regular line tools
@@ -581,9 +578,8 @@ export default {
const mid = elem.getAttribute('marker-mid');
const end = elem.getAttribute('marker-end');
curLine = elem;
$(elem)
.data('start_off', Boolean(start))
.data('end_off', Boolean(end));
dataStorage.put(elem, 'start_off', Boolean(start));
dataStorage.put(elem, 'end_off', Boolean(end));
if (elem.tagName === 'line' && mid) {
// Convert to polyline to accept mid-arrow
@@ -606,7 +602,8 @@ export default {
opacity: elem.getAttribute('opacity') || 1
}
});
$(elem).after(pline).remove();
elem.insertAdjacentElement('afterend', pline);
elem.remove();
svgCanvas.clearSelection();
pline.id = id;
svgCanvas.addToSelection([pline]);
@@ -615,7 +612,7 @@ export default {
}
// Update line if it's a connector
if (elem.getAttribute('class') === 'se_connector') {
const start = getElem(elData(elem, 'c_start'));
const start = getElem(dataStorage.get(elem, 'c_start'));
updateConnectors([start]);
} else {
updateConnectors();

View File

@@ -44,12 +44,14 @@ export default {
* @returns {void}
*/
function showPanel (on) {
let fcRules = $('#fc_rules');
if (!fcRules.length) {
fcRules = $('<style id="fc_rules"></style>').appendTo('head');
let fcRules = $id('fc_rules');
if (!fcRules) {
fcRules = document.createElement('style');
fcRules.setAttribute('id', 'fc_rules');
document.getElementsByTagName("head")[0].appendChild(fcRules);
}
fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#foreignObject_panel').toggle(on);
fcRules.textContent = !on ? '' : ' #tool_topath { display: none !important; }';
$id('foreignObject_panel').style.display = (on) ? 'block' : 'none';
}
/**
@@ -57,8 +59,10 @@ export default {
* @returns {void}
*/
function toggleSourceButtons (on) {
$('#tool_source_save, #tool_source_cancel').toggle(!on);
$('#foreign_save, #foreign_cancel').toggle(on);
$id('tool_source_save').style.display = (!on) ? 'block' : 'none';
$id('tool_source_cancel').style.display = (!on) ? 'block' : 'none';
$id('foreign_save').style.display = (on) ? 'block' : 'none';
$id('foreign_cancel').style.display = (on) ? 'block' : 'none';
}
let selElems,
@@ -75,7 +79,8 @@ export default {
const elt = selElems[0]; // The parent `Element` to append to
try {
// convert string into XML document
const newDoc = text2xml('<svg xmlns="' + NS.SVG + '" xmlns:xlink="' + NS.XLINK + '">' + xmlString + '</svg>');
const oi = (xmlString.indexOf('xmlns:oi') !== -1) ? ' xmlns:oi="' + NS.OI + '"' : '';
const newDoc = text2xml('<svg xmlns="' + NS.SVG + '" xmlns:xlink="' + NS.XLINK + '" '+ oi +'>' + xmlString + '</svg>');
// run it through our sanitizer to remove anything we do not support
svgCanvas.sanitizeSvg(newDoc.documentElement);
elt.replaceWith(svgdoc.importNode(newDoc.documentElement.firstChild, true));
@@ -102,10 +107,10 @@ export default {
elt.removeAttribute('fill');
const str = svgCanvas.svgToString(elt, 0);
$('#svg_source_textarea').val(str);
$('#svg_source_editor').fadeIn();
$id('svg_source_textarea').value = str;
$id('#svg_source_editor').style.display = 'block';
properlySourceSizeTextArea();
$('#svg_source_textarea').focus();
$id('svg_source_textarea').focus();
}
/**
@@ -188,33 +193,45 @@ export default {
const endChanges = function () {
$id("svg_source_editor").style.display = 'none';
editingforeign = false;
$('#svg_source_textarea').blur();
$id('svg_source_textarea').blur();
toggleSourceButtons(false);
};
// TODO: Needs to be done after orig icon loads
setTimeout(function () {
// Create source save/cancel buttons
/* const save = */ $('#tool_source_save').clone()
.hide().attr('id', 'foreign_save').unbind()
.appendTo('#tool_source_back').click(function () {
if (!editingforeign) { return; }
const toolSourceSave = $id('tool_source_save').cloneNode(true);
toolSourceSave.style.display = 'none';
toolSourceSave.id = 'foreign_save';
// unbind()
// const oldElement = $id('tool_source_save');
// oldElement.parentNode.replaceChild(toolSourceSave, oldElement);
$id('tool_source_back').append(toolSourceSave);
toolSourceSave.addEventListener('click', (e) => function () {
if (!editingforeign) { return; }
if (!setForeignString($('#svg_source_textarea').val())) {
const ok = seConfirm('Errors found. Revert to original?');
if (!ok) { return; }
endChanges();
} else {
endChanges();
}
// setSelectMode();
});
/* const cancel = */ $('#tool_source_cancel').clone()
.hide().attr('id', 'foreign_cancel').unbind()
.appendTo('#tool_source_back').click(function () {
if (!setForeignString($id('svg_source_textarea').value)) {
const ok = seConfirm('Errors found. Revert to original?');
if (!ok) { return; }
endChanges();
});
} else {
endChanges();
}
// setSelectMode();
});
var oldToolSourceCancel = $id('tool_source_cancel');
const toolSourceCancel = oldToolSourceCancel.cloneNode(true);
toolSourceCancel.style.display = 'none';
toolSourceCancel.id = 'foreign_cancel';
$id('tool_source_back').append(toolSourceCancel);
toolSourceCancel.addEventListener('click', (e) => function () {
endChanges();
});
// unbind()
// var oldToolSourceCancel = $id('tool_source_cancel');
// oldToolSourceCancel.parentNode.replaceChild(toolSourceCancel, oldToolSourceCancel);
}, 3000);
},
mouseDown (opts) {
@@ -256,7 +273,10 @@ export default {
if (svgCanvas.getMode() !== 'foreign' || !started) {
return undefined;
}
const attrs = $(newFO).attr(['width', 'height']);
const attrs = {
width: newFO.getAttribute('width'),
height: newFO.getAttribute('height'),
}
const keep = (attrs.width !== '0' || attrs.height !== '0');
svgCanvas.addToSelection([newFO], true);
@@ -274,9 +294,9 @@ export default {
const elem = selElems[i];
if (elem && elem.tagName === 'foreignObject') {
if (opts.selectedElement && !opts.multiselected) {
$('#foreign_font_size').val(elem.getAttribute('font-size'));
$('#foreign_width').val(elem.getAttribute('width'));
$('#foreign_height').val(elem.getAttribute('height'));
$id('foreign_font_size').value = elem.getAttribute('font-size');
$id('foreign_width').value = elem.getAttribute('width');
$id('foreign_height').value = elem.getAttribute('height');
showPanel(true);
} else {
showPanel(false);

View File

@@ -25,15 +25,17 @@ export default {
const svgEditor = this;
const strings = await loadExtensionTranslation(svgEditor.configObj.pref('lang'));
const {svgCanvas} = svgEditor;
const svgdoc = document.getElementById('svgcanvas').ownerDocument,
{assignAttributes} = svgCanvas,
hcanvas = document.createElement('canvas'),
canvBG = $('#canvasBackground'),
units = getTypeMap(), // Assumes prior `init()` call on `units.js` module
intervals = [0.01, 0.1, 1, 10, 100, 1000];
const {$id} = svgCanvas;
const svgdoc = document.getElementById('svgcanvas').ownerDocument;
const {assignAttributes} = svgCanvas;
const hcanvas = document.createElement('canvas');
const canvBG = $id('canvasBackground');
const units = getTypeMap(); // Assumes prior `init()` call on `units.js` module
const intervals = [0.01, 0.1, 1, 10, 100, 1000];
let showGrid = svgEditor.configObj.curConfig.showGrid || false;
$(hcanvas).hide().appendTo('body');
hcanvas.style.display = 'none';
document.body.appendChild(hcanvas);
const canvasGrid = svgdoc.createElementNS(NS.SVG, 'svg');
assignAttributes(canvasGrid, {
@@ -45,7 +47,7 @@ export default {
overflow: 'visible',
display: 'none'
});
canvBG.append(canvasGrid);
canvBG.appendChild(canvasGrid);
const gridDefs = svgdoc.createElementNS(NS.SVG, 'defs');
// grid-pattern
const gridPattern = svgdoc.createElementNS(NS.SVG, 'pattern');
@@ -67,7 +69,7 @@ export default {
});
gridPattern.append(gridimg);
gridDefs.append(gridPattern);
$('#canvasGrid').append(gridDefs);
$id('canvasGrid').appendChild(gridDefs);
// grid-box
const gridBox = svgdoc.createElementNS(NS.SVG, 'rect');
@@ -81,14 +83,14 @@ export default {
fill: 'url(#gridpattern)',
style: 'pointer-events: none; display:visible;'
});
$('#canvasGrid').append(gridBox);
$id('canvasGrid').appendChild(gridBox);
/**
*
* @param {Float} zoom
* @returns {void}
*/
function updateGrid (zoom) {
const updateGrid = (zoom) => {
// TODO: Try this with <line> elements, then compare performance difference
const unit = units[svgEditor.configObj.curConfig.baseUnit]; // 1 = 1px
const uMulti = unit * zoom;
@@ -141,11 +143,11 @@ export default {
*
* @returns {void}
*/
function gridUpdate () {
const gridUpdate = () => {
if (showGrid) {
updateGrid(svgCanvas.getZoom());
}
$('#canvasGrid').toggle(showGrid);
$id('canvasGrid').style.display = (showGrid) ? 'block' : 'none';
document.getElementById('view_grid').pressed = showGrid;
}
return {
@@ -154,15 +156,19 @@ export default {
if (showGrid) { updateGrid(zoom); }
},
callback () {
if (showGrid) {
gridUpdate();
}
},
events: {
id: 'view_grid',
click () {
// Add the button and its handler(s)
const buttonTemplate = document.createElement("template");
buttonTemplate.innerHTML = `
<se-button id="view_grid" title="Show grid" src="./images/grid.svg"></se-button>
`
$id('editor_panel').append(buttonTemplate.content.cloneNode(true));
$id('view_grid').addEventListener("click", () => {
svgEditor.configObj.curConfig.showGrid = showGrid = !showGrid;
gridUpdate();
});
if (showGrid) {
gridUpdate();
}
}
};

View File

@@ -1,3 +1,4 @@
/* eslint-disable no-unsanitized/property */
/* globals seConfirm */
/**
* @file ext-imagelib.js
@@ -188,8 +189,10 @@ export default {
await seConfirm(message);
transferStopped = true;
} else {
entry = $('<div>').text(message).data('id', curMeta.id);
preview.append(entry);
entry = document.createElement('div');
entry.textContent = message;
entry.dataset.id = curMeta.id;
preview.appendChild(entry);
curMeta.entry = entry;
}
@@ -256,51 +259,54 @@ export default {
// Try to find a title
// `dropXMLInternalSubset` is to help prevent the billion laughs attack
const xml = new DOMParser().parseFromString(dropXMLInternalSubset(response), 'text/xml').documentElement; // lgtm [js/xml-bomb]
title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
title = xml.querySelector('title').textContent || '(SVG #' + response.length + ')';
}
if (curMeta) {
$(preview).children().each(function () {
if ($(this).data('id') === id) {
Array.from(preview.children).forEach(function(element) {
if (element.dataset.id === id) {
if (curMeta.preview_url) {
$(this).html(
$('<span>').append(
$('<img>').attr('src', curMeta.preview_url),
title
)
);
const img = document.createElement("img");
img.src = curMeta.preview_url;
const span = document.createElement("span");
span.appendChild(img);
element.append(span);
} else {
$(this).text(title);
element.textContent = title;
}
submit.removeAttr('disabled');
submit.removeAttribute('disabled');
}
});
} else {
preview.append(
$('<div>').text(title)
);
submit.removeAttr('disabled');
const div = document.createElement("div");
div.textContent = title;
preview.appendChild(div);
submit.removeAttribute('disabled');
}
} else {
if (curMeta && curMeta.preview_url) {
title = curMeta.name || '';
entry = $('<span>').append(
$('<img>').attr('src', curMeta.preview_url),
title
);
entry = document.createElement('span');
const img = document.createElement("img");
img.src = curMeta.preview_url;
entry.appendChild(img);
entry.appendChild(document.createTextNode(title))
} else {
entry = $('<img>').attr('src', response);
entry = document.createElement("img");
entry.src = response;
}
if (curMeta) {
preview.children().each(function () {
if ($(this).data('id') === id) {
$(this).html(entry);
submit.removeAttr('disabled');
Array.from(preview.children).forEach(function(element) {
if (element.dataset.id === id) {
element.appendChild(entry);
submit.removeAttribute('disabled');
}
});
} else {
preview.append($('<div>').append(entry));
submit.removeAttr('disabled');
const div = document.createElement("div");
div.appendChild(entry);
preview.appendChild(div);
submit.removeAttribute('disabled');
}
}
break;
@@ -325,6 +331,23 @@ export default {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function toggleMultiLoop() {
$.each(multiArr, function (i) {
const type = this[0];
const data = this[1];
if (type === 'svg') {
svgCanvas.importSvgString(data);
} else {
importImage(data);
}
svgCanvas.moveSelectedElements(i * 20, i * 20, false);
});
while(preview.firstChild)
preview.removeChild(preview.firstChild);
multiArr = [];
$id("imgbrowse_holder").style.display = 'none';
}
/**
* @param {boolean} show
* @returns {void}
@@ -339,56 +362,18 @@ export default {
preview.setAttribute('style', `position: absolute;top: 45px;right: 10px;width: 180px;bottom: 45px;background: #fff;overflow: auto;`);
insertAfter($id('lib_framewrap'), preview);
/* submit = document.createElement('button');
submit = document.createElement('button');
submit.setAttribute('content', 'Import selected');
submit.setAttribute('disabled', true);
submit.textContent = 'Import selected';
submit.setAttribute('style', `position: absolute;bottom: 10px;right: -10px;`);
$id('imgbrowse').appendChild(submit);
submit.addEventListener('click', function () {
$.each(multiArr, function (i) {
const type = this[0];
const data = this[1];
if (type === 'svg') {
svgCanvas.importSvgString(data);
} else {
importImage(data);
}
svgCanvas.moveSelectedElements(i * 20, i * 20, false);
});
$(preview).empty();
multiArr = [];
$id("imgbrowse_holder").style.display = 'none';
})
submit.style.display = (show) ? 'block' : 'none';
*/
submit = $('<button disabled>Import selected</button>')
.appendTo('#imgbrowse')
.on('click touchend', function () {
$.each(multiArr, function (i) {
const type = this[0];
const data = this[1];
if (type === 'svg') {
svgCanvas.importSvgString(data);
} else {
importImage(data);
}
svgCanvas.moveSelectedElements(i * 20, i * 20, false);
});
$(preview).empty();
multiArr = [];
$id("imgbrowse_holder").style.display = 'none';
}).css({
position: 'absolute',
bottom: 10,
right: -10
});
submit.addEventListener('click', toggleMultiLoop);
submit.addEventListener('touchend', toggleMultiLoop);
}
submit.style.display = (show) ? 'block' : 'none';
preview.style.display = (show) ? 'block' : 'none';
submit.toggle(show);
}
/**
@@ -396,52 +381,79 @@ export default {
* @returns {void}
*/
function showBrowser () {
let browser = $('#imgbrowse');
if (!browser.length) {
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>' +
'</div></div>').insertAfter('#svg_editor');
browser = $('#imgbrowse');
let browser = $id('imgbrowse');
if (!browser) {
const div = document.createElement('div');
div.id = 'imgbrowse_holder';
div.innerHTML = '<div id=imgbrowse class=toolbar_button></div>';
insertAfter($id('svg_editor'), div);
browser = $id('imgbrowse');
const allLibs = imagelibStrings.select_lib;
const libOpts = $('<ul id=imglib_opts>').appendTo(browser);
const frame = $('<iframe src="javascript:0"/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>');
const divFrameWrap = document.createElement('div');
divFrameWrap.id = 'lib_framewrap';
const header = $('<h1>').prependTo(browser).text(allLibs).css({
position: 'absolute',
top: 0,
left: 0,
width: '100%'
const libOpts = document.createElement('ul');
libOpts.id = 'imglib_opts';
browser.append(libOpts);
const frame = document.createElement('iframe');
frame.src = "javascript:0";
frame.style.display = 'none';
divFrameWrap.append(frame);
browser.prepend(divFrameWrap);
const header = document.createElement('h1');
browser.prepend(header);
header.textContent = allLibs;
header.setAttribute('style', `position: absolute;top: 0;left: 0;width: 100%;`);
const button = document.createElement('button');
// eslint-disable-next-line max-len
button.innerHTML = '<img class="svg_icon" src="./images/cancel.svg" alt="icon" width="16" height="16" />' + uiStrings.common.cancel ;
browser.appendChild(button);
button.addEventListener('click', function () {
$id("imgbrowse_holder").style.display = 'none';
});
button.addEventListener('touchend', function () {
$id("imgbrowse_holder").style.display = 'none';
});
button.setAttribute('style', `position: absolute;top: 5;right: -10;`);
const leftBlock = document.createElement('span');
leftBlock.setAttribute('style', `position: absolute;top: 5;left: 10;`);
browser.appendChild(leftBlock);
const back = document.createElement('button');
back.style.visibility = "hidden";
// eslint-disable-next-line max-len
$('<button><img class="svg_icon" src="./images/cancel.svg" alt="icon" width="16" height="16" />' + uiStrings.common.cancel + '</button>')
.appendTo(browser)
.on('click touchend', function () {
$id("imgbrowse_holder").style.display = 'none';
}).css({
position: 'absolute',
top: 5,
right: -10
});
back.innerHTML = '<img class="svg_icon" src="./images/library.svg" alt="icon" width="16" height="16" />' + imagelibStrings.show_list;
leftBlock.appendChild(back);
back.addEventListener('click', function () {
frame.setAttribute('src', 'about:blank');
frame.style.display = 'none';
libOpts.style.display = 'block';
header.textContent = allLibs;
back.style.display = 'none';
});
back.addEventListener('touchend', function () {
frame.setAttribute('src', 'about:blank');
frame.style.display = 'none';
libOpts.style.display = 'block';
header.textContent = allLibs;
back.style.display = 'none';
});
back.setAttribute('style', `margin-right: 5px;`);
back.style.display = 'none';
const leftBlock = $('<span>').css({position: 'absolute', top: 5, left: 10}).appendTo(browser);
// eslint-disable-next-line max-len
const back = $('<button hidden><img class="svg_icon" src="./images/library.svg" alt="icon" width="16" height="16" />' + imagelibStrings.show_list + '</button>')
.appendTo(leftBlock)
.on('click touchend', function () {
frame.attr('src', 'about:blank').hide();
libOpts.show();
header.text(allLibs);
back.hide();
}).css({
'margin-right': 5
}).hide();
/* const type = */ $('<select><option value=s>' +
imagelibStrings.import_single + '</option><option value=m>' +
imagelibStrings.import_multi + '</option><option value=o>' +
imagelibStrings.open + '</option></select>').appendTo(leftBlock).change(function () {
mode = $(this).val();
const select = document.createElement('select');
select.innerHTML = '<select><option value=s>' +
imagelibStrings.import_single + '</option><option value=m>' +
imagelibStrings.import_multi + '</option><option value=o>' +
imagelibStrings.open + '</option>';
leftBlock.appendChild(select);
select.addEventListener('change', function () {
mode = this.value;
switch (mode) {
case 's':
case 'o':
@@ -453,23 +465,30 @@ export default {
toggleMulti(true);
break;
}
}).css({
'margin-top': 10
});
select.setAttribute('style', `margin-top: 10px;`);
imagelibStrings.imgLibs.forEach(function ({name, url, description}) {
$('<li>')
.appendTo(libOpts)
.text(name)
.on('click touchend', function () {
frame.attr(
'src',
url
).show();
header.text(name);
libOpts.hide();
back.show();
}).append(`<span>${description}</span>`);
const li = document.createElement('li');
libOpts.appendChild(li);
li.textContent = name;
li.addEventListener('click', function () {
frame.setAttribute('src', url);
frame.style.display = 'block';
header.textContent = name;
libOpts.style.display = 'none';
back.style.display = 'block';
});
li.addEventListener('touchend', function () {
frame.setAttribute('src', url);
frame.style.display = 'block';
header.textContent = name;
libOpts.style.display = 'none';
back.style.display = 'block';
});
var span = document.createElement("span");
span.textContent = description;
li.appendChild(span);
});
} else {
$id("imgbrowse_holder").style.display = 'block';
@@ -487,81 +506,81 @@ export default {
svgicons: 'ext-imagelib.xml',
events,
callback () {
$('<style>').text(
'#imgbrowse_holder {' +
'position: absolute;' +
'top: 0;' +
'left: 0;' +
'width: 100%;' +
'height: 100%;' +
'background-color: rgba(0, 0, 0, .5);' +
'z-index: 5;' +
'}' +
'#imgbrowse {' +
'position: absolute;' +
'top: 25px;' +
'left: 25px;' +
'right: 25px;' +
'bottom: 25px;' +
'min-width: 300px;' +
'min-height: 200px;' +
'background: #B0B0B0;' +
'border: 1px outset #777;' +
'}' +
'#imgbrowse h1 {' +
'font-size: 20px;' +
'margin: .4em;' +
'text-align: center;' +
'}' +
'#lib_framewrap,' +
'#imgbrowse > ul {' +
'position: absolute;' +
'top: 45px;' +
'left: 10px;' +
'right: 10px;' +
'bottom: 10px;' +
'background: white;' +
'margin: 0;' +
'padding: 0;' +
'}' +
'#imgbrowse > ul {' +
'overflow: auto;' +
'}' +
'#imgbrowse > div {' +
'border: 1px solid #666;' +
'}' +
'#imglib_preview > div {' +
'padding: 5px;' +
'font-size: 12px;' +
'}' +
'#imglib_preview img {' +
'display: block;' +
'margin: 0 auto;' +
'max-height: 100px;' +
'}' +
'#imgbrowse li {' +
'list-style: none;' +
'padding: .5em;' +
'background: #E8E8E8;' +
'border-bottom: 1px solid #B0B0B0;' +
'line-height: 1.2em;' +
'font-style: sans-serif;' +
'}' +
'#imgbrowse li > span {' +
'color: #666;' +
'font-size: 15px;' +
'display: block;' +
'}' +
'#imgbrowse li:hover {' +
'background: #FFC;' +
'cursor: pointer;' +
'}' +
'#imgbrowse iframe {' +
'width: 100%;' +
'height: 100%;' +
'border: 0;' +
'}'
).appendTo('head');
const style = document.createElement('style');
style.textContent = '#imgbrowse_holder {' +
'position: absolute;' +
'top: 0;' +
'left: 0;' +
'width: 100%;' +
'height: 100%;' +
'background-color: rgba(0, 0, 0, .5);' +
'z-index: 5;' +
'}' +
'#imgbrowse {' +
'position: absolute;' +
'top: 25px;' +
'left: 25px;' +
'right: 25px;' +
'bottom: 25px;' +
'min-width: 300px;' +
'min-height: 200px;' +
'background: #B0B0B0;' +
'border: 1px outset #777;' +
'}' +
'#imgbrowse h1 {' +
'font-size: 20px;' +
'margin: .4em;' +
'text-align: center;' +
'}' +
'#lib_framewrap,' +
'#imgbrowse > ul {' +
'position: absolute;' +
'top: 45px;' +
'left: 10px;' +
'right: 10px;' +
'bottom: 10px;' +
'background: white;' +
'margin: 0;' +
'padding: 0;' +
'}' +
'#imgbrowse > ul {' +
'overflow: auto;' +
'}' +
'#imgbrowse > div {' +
'border: 1px solid #666;' +
'}' +
'#imglib_preview > div {' +
'padding: 5px;' +
'font-size: 12px;' +
'}' +
'#imglib_preview img {' +
'display: block;' +
'margin: 0 auto;' +
'max-height: 100px;' +
'}' +
'#imgbrowse li {' +
'list-style: none;' +
'padding: .5em;' +
'background: #E8E8E8;' +
'border-bottom: 1px solid #B0B0B0;' +
'line-height: 1.2em;' +
'font-style: sans-serif;' +
'}' +
'#imgbrowse li > span {' +
'color: #666;' +
'font-size: 15px;' +
'display: block;' +
'}' +
'#imgbrowse li:hover {' +
'background: #FFC;' +
'cursor: pointer;' +
'}' +
'#imgbrowse iframe {' +
'width: 100%;' +
'height: 100%;' +
'border: 0;' +
'}';
document.head.appendChild(style);
}
};
}

View File

@@ -1,49 +1,52 @@
/* globals jQuery */
const $ = jQuery;
$('a').click(function () {
const {href} = this;
const target = window.parent;
const post = (message) => {
// Todo: Make origin customizable as set by opening window
// Todo: If dropping IE9, avoid stringifying
target.postMessage(JSON.stringify({
namespace: 'imagelib',
...message
}), '*');
};
// Convert Non-SVG images to data URL first
// (this could also have been done server-side by the library)
// Send metadata (also indicates file is about to be sent)
post({
name: $(this).text(),
id: href
});
if (!href.includes('.svg')) {
const img = new Image();
img.addEventListener('load', function () {
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
// load the raster image into the canvas
canvas.getContext('2d').drawImage(this, 0, 0);
// retrieve the data: URL
let data;
try {
data = canvas.toDataURL();
} catch (err) {
// This fails in Firefox with `file:///` URLs :(
// Todo: This could use a generic alert library instead
alert('Data URL conversion failed: ' + err);
data = '';
}
post({href, data});
const atags = document.querySelectorAll('a');
Array.prototype.forEach.call(atags, function (aEle, i) {
aEle.addEventListener('click', function (event) {
const { href } = event.currentTarget;
const target = window.parent;
const post = (message) => {
// Todo: Make origin customizable as set by opening window
// Todo: If dropping IE9, avoid stringifying
target.postMessage(JSON.stringify({
namespace: 'imagelib',
...message
}), '*');
};
// Convert Non-SVG images to data URL first
// (this could also have been done server-side by the library)
// Send metadata (also indicates file is about to be sent)
post({
name: event.currentTarget.textContent,
id: href
});
img.src = href;
} else {
// Do ajax request for image's href value
$.get(href, function (data) {
post({href, data});
}, 'html'); // 'html' is necessary to keep returned data as a string
}
return false;
if (!href.includes('.svg')) {
const img = new Image();
img.addEventListener('load', function () {
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
// load the raster image into the canvas
canvas.getContext('2d').drawImage(this, 0, 0);
// retrieve the data: URL
let data;
try {
data = canvas.toDataURL();
} catch (err) {
// This fails in Firefox with `file:///` URLs :(
// Todo: This could use a generic alert library instead
alert('Data URL conversion failed: ' + err);
data = '';
}
post({ href, data });
});
img.src = href;
} else {
// Do ajax request for image's href value
$.get(href, function (data) {
post({ href, data });
}, 'html'); // 'html' is necessary to keep returned data as a string
}
return false;
})
});

View File

@@ -121,9 +121,17 @@ export default {
*/
function setIcon (pos, id) {
if (id.substr(0, 1) !== '\\') { id = '\\textmarker'; }
const ci = '#' + idPrefix + pos + '_' + id.substr(1);
svgEditor.setIcon('#cur_' + pos + '_marker_list', $(ci).children());
$(ci).addClass('current').siblings().removeClass('current');
const ci = idPrefix + pos + '_' + id.substr(1);
console.log(ci)
console.log('cur_' + pos + '_marker_list')
svgEditor.setIcon('cur_' + pos + '_marker_list', $id(ci).children);
$id(ci).classList.add('current');
const siblings = Array.prototype.filter.call($id(ci).parentNode.children, function(child){
return child !== $id(ci);
});
Array.from(siblings).forEach(function(sibling) {
sibling.classList.remove('current');
});
}
let selElems;
@@ -134,7 +142,7 @@ export default {
* @returns {void}
*/
function showPanel (on) {
$('#marker_panel').toggle(on);
$id('marker_panel').style.display = (on) ? 'block' : 'none';
if (on) {
const el = selElems[0];
@@ -142,11 +150,11 @@ export default {
let val, ci;
$.each(mtypes, function (i, pos) {
const m = getLinked(el, 'marker-' + pos);
const txtbox = $('#' + pos + '_marker');
const txtbox = $id(pos + '_marker');
if (!m) {
val = '\\nomarker';
ci = val;
txtbox.hide(); // hide text box
txtbox.style.display = 'none';
} else {
if (!m.attributes.se_type) { return; } // not created by this extension
val = '\\' + m.attributes.se_type.textContent;
@@ -155,10 +163,10 @@ export default {
val = m.lastChild.textContent;
// txtbox.show(); // show text box
} else {
txtbox.hide(); // hide text box
txtbox.style.display = 'none';
}
}
txtbox.val(val);
txtbox.value = val;
setIcon(pos, ci);
});
}
@@ -302,7 +310,8 @@ export default {
batchCmd.addSubCommand(new S.RemoveElementCommand(elem, elem.parentNode));
batchCmd.addSubCommand(new S.InsertElementCommand(pline));
$(elem).after(pline).remove();
elem.insertAdjacentElement('afterend', pline);
elem.remove();
svgCanvas.clearSelection();
pline.id = id;
svgCanvas.addToSelection([pline]);
@@ -320,7 +329,7 @@ export default {
const markerName = 'marker-' + pos;
const el = selElems[0];
const marker = getLinked(el, markerName);
if (marker) { $(marker).remove(); }
if (marker) { marker.remove(); }
el.removeAttribute(markerName);
let val = this.value;
if (val === '') { val = '\\nomarker'; }
@@ -379,7 +388,7 @@ export default {
const len = el.id.length;
const linkid = url.substr(-len - 1, len);
if (el.id !== linkid) {
const val = $('#' + pos + '_marker').attr('value');
const val = $id(pos + '_marker').getAttribute('value');
addMarker(id, val);
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
if (el.tagName === 'line' && pos === 'mid') { el = convertline(el); }
@@ -396,11 +405,8 @@ export default {
* @returns {void}
*/
function triggerTextEntry (pos, val) {
$('#' + pos + '_marker').val(val);
$('#' + pos + '_marker').change();
// const txtbox = $('#'+pos+'_marker');
// if (val.substr(0,1)=='\\') {txtbox.hide();}
// else {txtbox.show();}
$id(pos + '_marker').value = val;
$id(pos + '_marker').change();
}
/**
@@ -408,7 +414,7 @@ export default {
* @returns {void} Resolves to `undefined`
*/
function showTextPrompt (pos) {
let def = $('#' + pos + '_marker').val();
let def = $id(pos + '_marker').value;
if (def.substr(0, 1) === '\\') { def = ''; }
// eslint-disable-next-line no-alert
const txt = prompt('Enter text for ' + pos + ' marker', def);

View File

@@ -82,7 +82,7 @@ export default {
* @returns {void}
*/
function saveMath () {
const code = $('#mathjax_code_textarea').val();
const code = $id('mathjax_code_textarea').value;
// displaystyle to force MathJax NOT to use the inline style. Because it is
// less fancy!
MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']);
@@ -145,37 +145,30 @@ export default {
// Only load Mathjax when needed, we don't want to strain Svg-Edit any more.
// From this point on it is very probable that it will be needed, so load it.
if (mathjaxLoaded === false) {
$(
'<div id="mathjax">' +
'<!-- Here is where MathJax creates the math -->' +
'<div id="mathjax_creator" class="tex2jax_process" style="display:none">' +
'$${}$$' +
'</div>' +
'<div id="mathjax_overlay"></div>' +
'<div id="mathjax_container">' +
'<div id="tool_mathjax_back" class="toolbar_button">' +
'<button id="tool_mathjax_save">OK</button>' +
'<button id="tool_mathjax_cancel">Cancel</button>' +
'</div>' +
'<fieldset>' +
'<legend id="mathjax_legend">Mathematics Editor</legend>' +
'<label>' +
'<span id="mathjax_explication">Please type your mathematics in ' +
'<a href="https://en.wikipedia.org/wiki/Help:' +
'Displaying_a_formula" target="_blank">TeX</a> code.' +
'</span></label>' +
'<textarea id="mathjax_code_textarea" spellcheck="false"></textarea>' +
'</fieldset>' +
'</div>' +
'</div>'
).insertAfter('#svg_prefs').hide();
// Make the MathEditor draggable.
// TODO: unable to reach this place
/* $('#mathjax_container').draggable({
cancel: 'button,fieldset',
containment: 'window'
}); */
const div = document.createElement('div');
div.id = 'mathjax';
div.innerHTML = '<!-- Here is where MathJax creates the math -->' +
'<div id="mathjax_creator" class="tex2jax_process" style="display:none">' +
'$${}$$' +
'</div>' +
'<div id="mathjax_overlay"></div>' +
'<div id="mathjax_container">' +
'<div id="tool_mathjax_back" class="toolbar_button">' +
'<button id="tool_mathjax_save">OK</button>' +
'<button id="tool_mathjax_cancel">Cancel</button>' +
'</div>' +
'<fieldset>' +
'<legend id="mathjax_legend">Mathematics Editor</legend>' +
'<label>' +
'<span id="mathjax_explication">Please type your mathematics in ' +
'<a href="https://en.wikipedia.org/wiki/Help:' +
'Displaying_a_formula" target="_blank">TeX</a> code.' +
'</span></label>' +
'<textarea id="mathjax_code_textarea" spellcheck="false"></textarea>' +
'</fieldset>' +
'</div>';
$id('svg_prefs').parentNode.insertBefore(div, $id('svg_prefs').nextSibling);
div.style.display = 'none';
// Add functionality and picture to cancel button.
$('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true))
.on('click touched', function () {
@@ -238,59 +231,57 @@ export default {
return undefined;
},
callback () {
$('<style>').text(
'#mathjax fieldset{' +
'padding: 5px;' +
'margin: 5px;' +
'border: 1px solid #DDD;' +
'}' +
'#mathjax label{' +
'display: block;' +
'margin: .5em;' +
'}' +
'#mathjax legend {' +
'max-width:195px;' +
'}' +
'#mathjax_overlay {' +
'position: absolute;' +
'top: 0;' +
'left: 0;' +
'right: 0;' +
'bottom: 0;' +
'background-color: black;' +
'opacity: 0.6;' +
'z-index: 20000;' +
'}' +
'#mathjax_container {' +
'position: absolute;' +
'top: 50px;' +
'padding: 10px;' +
'background-color: #B0B0B0;' +
'border: 1px outset #777;' +
'opacity: 1.0;' +
'font-family: Verdana, Helvetica, sans-serif;' +
'font-size: .8em;' +
'z-index: 20001;' +
'}' +
'#tool_mathjax_back {' +
'margin-left: 1em;' +
'overflow: auto;' +
'}' +
'#mathjax_legend{' +
'font-weight: bold;' +
'font-size:1.1em;' +
'}' +
'#mathjax_code_textarea {\\n' +
'margin: 5px .7em;' +
'overflow: hidden;' +
'width: 416px;' +
'display: block;' +
'height: 100px;' +
'}'
).appendTo('head');
// Add the MathJax configuration.
// $(mathjaxConfiguration).appendTo('head');
const head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.textContent = '#mathjax fieldset{' +
'padding: 5px;' +
'margin: 5px;' +
'border: 1px solid #DDD;' +
'}' +
'#mathjax label{' +
'display: block;' +
'margin: .5em;' +
'}' +
'#mathjax legend {' +
'max-width:195px;' +
'}' +
'#mathjax_overlay {' +
'position: absolute;' +
'top: 0;' +
'left: 0;' +
'right: 0;' +
'bottom: 0;' +
'background-color: black;' +
'opacity: 0.6;' +
'z-index: 20000;' +
'}' +
'#mathjax_container {' +
'position: absolute;' +
'top: 50px;' +
'padding: 10px;' +
'background-color: #B0B0B0;' +
'border: 1px outset #777;' +
'opacity: 1.0;' +
'font-family: Verdana, Helvetica, sans-serif;' +
'font-size: .8em;' +
'z-index: 20001;' +
'}' +
'#tool_mathjax_back {' +
'margin-left: 1em;' +
'overflow: auto;' +
'}' +
'#mathjax_legend{' +
'font-weight: bold;' +
'font-size:1.1em;' +
'}' +
'#mathjax_code_textarea {\\n' +
'margin: 5px .7em;' +
'overflow: hidden;' +
'width: 416px;' +
'display: block;' +
'height: 100px;' +
'}';
head.appendChild(style);
}
};
}

View File

@@ -72,7 +72,7 @@ export default {
* @returns {void}
*/
function showPanel (on) {
$('#placemark_panel').toggle(on);
$id('placemark_panel').style.display = (on) ? 'block' : 'none';
}
/**
@@ -104,10 +104,11 @@ export default {
const items = txt.split(';');
selElems.forEach((elem) => {
if (elem && elem.getAttribute('class').includes('placemark')) {
$(elem).children().each((_, i) => {
var elements = elem.children;
Array.prototype.forEach.call(elements, function(i, _){
const [, , type, n] = i.id.split('_');
if (type === 'txt') {
$(i).text(items[n]);
t.textContent = items[n];
}
});
}
@@ -124,10 +125,11 @@ export default {
font = font.join(' ');
selElems.forEach((elem) => {
if (elem && elem.getAttribute('class').includes('placemark')) {
$(elem).children().each((_, i) => {
var elements = elem.children;
Array.prototype.forEach.call(elements, function(i, _){
const [, , type] = i.id.split('_');
if (type === 'txt') {
$(i).attr({'font-family': font, 'font-size': fontSize});
i.style.cssText = 'font-family:' + font + ';font-size:'+fontSize+';';
}
});
}
@@ -141,13 +143,12 @@ export default {
function addMarker (id, val) {
let marker = svgCanvas.getElem(id);
if (marker) { return undefined; }
// console.log(id);
if (val === '' || val === 'nomarker') { return undefined; }
const color = svgCanvas.getColor('stroke');
// NOTE: Safari didn't like a negative value in viewBox
// so we use a standardized 0 0 100 100
// with 50 50 being mapped to the marker position
const scale = 2;// parseFloat($('#marker_size').val());
const scale = 2;
const strokeWidth = 10;
let refX = 50;
const refY = 50;
@@ -200,7 +201,7 @@ export default {
function setMarker (el, val) {
const markerName = 'marker-start';
const marker = getLinked(el, markerName);
if (marker) { $(marker).remove(); }
if (marker) { marker.remove(); }
el.removeAttribute(markerName);
if (val === 'nomarker') {
svgCanvas.call('changed', [el]);
@@ -249,7 +250,7 @@ export default {
const len = el.id.length;
const linkid = url.substr(-len - 1, len);
if (el.id !== linkid) {
const val = $('#placemark_marker').attr('value') || 'leftarrow';
const val = $id('placemark_marker').getAttribute('value') || 'leftarrow';
addMarker(id, val);
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
svgCanvas.call('changed', selElems);
@@ -264,7 +265,7 @@ export default {
const parts = this.id.split('_');
let val = parts[2];
if (parts[3]) { val += '_' + parts[3]; }
$('#placemark_marker').attr('value', val);
$id('placemark_marker').setAttribute('value', val);
}
/**
@@ -368,8 +369,8 @@ export default {
if (svgCanvas.getMode() === 'placemark') {
started = true;
const id = svgCanvas.getNextId();
const items = $('#placemarkText').val().split(';');
let font = $('#placemarkFont').val().split(' ');
const items = $id('placemarkText').value.split(';');
let font = $id('placemarkFont').value.split(' ');
const fontSize = Number.parseInt(font.pop());
font = font.join(' ');
const x0 = opts.start_x + 10, y0 = opts.start_y + 10;
@@ -453,7 +454,7 @@ export default {
});
setMarker(
newPM.firstElementChild,
$('#placemark_marker').attr('value') || 'leftarrow'
$id('placemark_marker').getAttribute('value') || 'leftarrow'
);
return {
started: true
@@ -468,11 +469,16 @@ export default {
if (svgCanvas.getMode() === 'placemark') {
const x = opts.mouse_x / svgCanvas.getZoom();
const y = opts.mouse_y / svgCanvas.getZoom();
const {fontSize, maxlen, lines, px, py} = $(newPM).attr(
['fontSize', 'maxlen', 'lines', 'px', 'py']
);
$(newPM).attr({x, y});
$(newPM).children().each((_, i) => {
const fontSize = newPM.getAttribute('fontSize');
const maxlen = newPM.getAttribute('maxlen');
const lines = newPM.getAttribute('lines');
const px = newPM.getAttribute('px');
const py = newPM.getAttribute('py');
newPM.setAttribute('x', x);
newPM.setAttribute('y', y);
const elements = newPM.children;
Array.prototype.forEach.call(elements, function(i, _){
const [, , type, n] = i.id.split('_');
const y0 = y + (fontSize + 6) * n,
x0 = x + maxlen * fontSize * 0.5 + fontSize;
@@ -509,7 +515,10 @@ export default {
},
mouseUp () {
if (svgCanvas.getMode() === 'placemark') {
const {x, y, px, py} = $(newPM).attr(['x', 'y', 'px', 'py']);
const x = newPM.getAttribute('x');
const y = newPM.getAttribute('y');
const px = newPM.getAttribute('px');
const py = newPM.getAttribute('py');
return {
keep: (x != px && y != py), // eslint-disable-line eqeqeq
element: newPM
@@ -523,16 +532,17 @@ export default {
selElems.forEach((elem) => {
if (elem && elem.getAttribute('class').includes('placemark')) {
const txt = [];
$(elem).children().each((n, i) => {
const elements = elem.children;
Array.prototype.forEach.call(elements, function(i, n){
const [, , type] = i.id.split('_');
if (type === 'txt') {
$('#placemarkFont').val(
$id('placemarkFont').value = (
i.getAttribute('font-family') + ' ' + i.getAttribute('font-size')
);
txt.push($(i).text());
txt.push(i.textContent);
}
});
$('#placemarkText').val(txt.join(';'));
$id('placemarkText').value = txt.join(';');
showPanel(true);
} else {
showPanel(false);

View File

@@ -24,42 +24,26 @@ export default {
const svgEditor = this;
const {svgCanvas} = svgEditor;
const {$id} = svgCanvas;
const {$} = S, // {svgcontent}
// addElem = svgCanvas.addSVGElementFromJson,
editingitex = false;
const {$} = S;
const editingitex = false;
const strings = await loadExtensionTranslation(svgEditor.configObj.pref('lang'));
let selElems,
// svgdoc = S.svgroot.parentNode.ownerDocument,
// newFOG, newFOGParent, newDef, newImageName, newMaskID, modeChangeG,
// edg = 0,
// undoCommand = 'Not image';
started, newFO;
let selElems;
let started;
let newFO;
/**
* @param {boolean} on
* @returns {void}
*/
function showPanel (on) {
let fcRules = $('#fc_rules');
if (!fcRules.length) {
fcRules = $('<style id="fc_rules"></style>').appendTo('head');
}
fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#polygon_panel').toggle(on);
}
/*
function toggleSourceButtons(on){
$('#tool_source_save, #tool_source_cancel').toggle(!on);
$('#polygon_save, #polygon_cancel').toggle(on);
}
*/
const showPanel = (on) => {
$id('polygon_panel').style.display = (on) ? 'block' : 'none';
}
/**
* @param {string} attr
* @param {string|Float} val
* @returns {void}
*/
function setAttr (attr, val) {
const setAttr = (attr, val) => {
svgCanvas.changeSelectedAttribute(attr, val);
svgCanvas.call('changed', selElems);
}
@@ -68,88 +52,50 @@ export default {
* @param {Float} n
* @returns {Float}
*/
function cot (n) {
return 1 / Math.tan(n);
}
const cot = (n) => (1 / Math.tan(n));
/**
* @param {Float} n
* @returns {Float}
*/
function sec (n) {
return 1 / Math.cos(n);
}
const sec = (n) => (1 / Math.cos(n));
/**
* Obtained from http://code.google.com/p/passenger-top/source/browse/instiki/public/svg-edit/editor/extensions/ext-itex.js?r=3
* This function sets the content of of the currently-selected foreignObject element,
* based on the itex contained in string.
* @param {string} tex The itex text.
* @returns {boolean} This function returns false if the set was unsuccessful, true otherwise.
*/
const events = {
id: 'tool_polygon',
click () {
svgCanvas.setMode('polygon');
showPanel(true);
}
};
const contextTools = [{
type: 'input',
panel: 'polygon_panel',
id: 'polySides',
size: 3,
defval: 5,
events: {
change () {
setAttr('sides', this.value);
}
}
}];
return {
name: strings.name,
events,
context_tools: strings.contextTools.map((contextTool, i) => {
return Object.assign(contextTools[i], contextTool);
}),
// The callback should be used to load the DOM with the appropriate UI items
callback () {
if($id("polygon_panel") !== null) $id("polygon_panel").style.display = 'none';
const endChanges = function () {
// Todo: Missing?
};
// Add the button and its handler(s)
// Note: the star extension may also add the same flying button so we check first
if ($id('tools_polygon') === null) {
const buttonTemplate = document.createElement("template");
buttonTemplate.innerHTML = `
<se-flyingbutton id="tools_polygon" title="Polygone/Star Tool">
<se-button id="tool_polygon" title="Polygon Tool" src="./images/polygon.svg"></se-button>
<se-button id="tool_star" title="Star Tool" src="./images/star.svg"></se-button>
</se-flyingbutton>
`
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
}
$id('tool_polygon').addEventListener("click", () => {
if (this.leftPanel.updateLeftPanel('tool_polygon')) {
svgCanvas.setMode('polygon');
showPanel(true);
}
});
// TODO: Needs to be done after orig icon loads
setTimeout(function () {
// Create source save/cancel buttons
/* const save = */ $('#tool_source_save').clone().hide().attr(
'id', 'polygon_save'
).unbind().appendTo(
'#tool_source_back'
).click(function () {
if (!editingitex) {
return;
}
// Todo: Uncomment the setItexString() function above and handle ajaxEndpoint?
/*
if (!setItexString($('#svg_source_textarea').val())) {
const ok = seConfirm('Errors found. Revert to original?', function (ok) {
if (!ok) {
return false;
}
endChanges();
} else { */
endChanges();
// }
// setSelectMode();
});
/* const cancel = */ $('#tool_source_cancel').clone().hide().attr(
'id', 'polygon_cancel'
).unbind().appendTo('#tool_source_back').click(function () {
endChanges();
});
}, 3000);
// Add the context panel and its handler(s)
const panelTemplate = document.createElement("template");
panelTemplate.innerHTML = `
<div id="polygon_panel">
<se-spin-input size="3" id="polySides" min=1 step=1 value=5 label="sides">
</se-spin-input>
</div>
`
$id('tools_top').appendChild(panelTemplate.content.cloneNode(true));
$id("polygon_panel").style.display = 'none';
$id("polySides").addEventListener("change", (event) => {
setAttr('sides', event.target.value);
});
},
mouseDown (opts) {
if (svgCanvas.getMode() !== 'polygon') {
@@ -188,12 +134,18 @@ export default {
if (!started || svgCanvas.getMode() !== 'polygon') {
return undefined;
}
// const e = opts.event;
const c = $(newFO).attr(['cx', 'cy', 'sides', 'orient', 'fill', 'strokecolor', 'strokeWidth']);
const cx = Number(newFO.getAttribute('cx'));
const cy = Number(newFO.getAttribute('cy'));
const sides = Number(newFO.getAttribute('sides'));
const orient = newFO.getAttribute('orient');
const fill = newFO.getAttribute('fill');
const strokecolor = newFO.getAttribute('strokecolor');
const strokeWidth = Number(newFO.getAttribute('strokeWidth'));
let x = opts.mouse_x;
let y = opts.mouse_y;
const {cx, cy, fill, strokecolor, strokeWidth, sides} = c, // {orient} = c,
edg = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5;
const edg = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5;
newFO.setAttribute('edge', edg);
const inradius = (edg / 2) * cot(Math.PI / sides);
@@ -212,10 +164,6 @@ export default {
newFO.setAttribute('fill', fill);
newFO.setAttribute('stroke', strokecolor);
newFO.setAttribute('stroke-width', strokeWidth);
// newFO.setAttribute('transform', 'rotate(-90)');
// const shape = newFO.getAttribute('shape');
// newFO.append(poly);
// DrawPoly(cx, cy, sides, edg, orient);
return {
started: true
};
@@ -225,8 +173,8 @@ export default {
if (svgCanvas.getMode() !== 'polygon') {
return undefined;
}
const attrs = $(newFO).attr('edge');
const keep = (attrs.edge !== '0');
const edge = newFO.getAttribute('edge');
const keep = (edge !== '0');
// svgCanvas.addToSelection([newFO], true);
return {
keep,
@@ -242,7 +190,7 @@ export default {
const elem = selElems[i];
if (elem && elem.getAttribute('shape') === 'regularPoly') {
if (opts.selectedElement && !opts.multiselected) {
$('#polySides').val(elem.getAttribute('sides'));
$id('polySides').value = elem.getAttribute('sides');
showPanel(true);
} else {

View File

@@ -27,15 +27,18 @@ export default {
const svgEditor = this;
const strings = await loadExtensionTranslation(svgEditor.configObj.pref('lang'));
const {svgCanvas} = svgEditor;
const {$id} = svgCanvas;
const saveSvgAction = '/+modify';
// Create upload target (hidden iframe)
// Hiding by size instead of display to avoid FF console errors
// with `getBBox` in browser.js `supportsPathBBox_`)
/* const target = */ $(
`<iframe name="output_frame" title="${strings.hiddenframe}"
style="width: 0; height: 0;" src="data:text/html;base64,PGh0bWw+PC9odG1sPg=="/>`
).appendTo('body');
const iframe = document.createElement('IFRAME');
iframe.src="data:text/html;base64,PGh0bWw+PC9odG1sPg==";
document.body.append(iframe);
iframe.name = "output_frame";
iframe.contentWindow.document.title = strings.hiddenframe;
iframe.style.cssText = "width:0;height:0;";
svgEditor.setCustomHandlers({
async save (win, data) {
@@ -43,27 +46,33 @@ export default {
const {pathname} = new URL(location);
const name = pathname.replace(/\/+get\//, '');
const svgData = encode64(svg);
if (!$('#export_canvas').length) {
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
if (!$id('export_canvas')) {
const canvas = document.createElement('canvas');
canvas.setAttribute('id', 'export_canvas');
canvas.style.display = 'none';
document.body.appendChild(canvas);
}
const c = $('#export_canvas')[0];
c.width = svgCanvas.contentW;
c.height = svgCanvas.contentH;
const c = $id('export_canvas');
c.style.width = svgCanvas.contentW;
c.style.height = svgCanvas.contentH;
await canvg(c, svg);
const datauri = c.toDataURL('image/png');
// const {uiStrings} = svgEditor;
const pngData = encode64(datauri); // Brett: This encoding seems unnecessary
/* const form = */ $('<form>').attr({
method: 'post',
action: saveSvgAction + '/' + name,
target: 'output_frame'
}).append(`
<input type="hidden" name="png_data" value="${pngData}">
<input type="hidden" name="filepath" value="${svgData}">
<input type="hidden" name="filename" value="drawing.svg">
<input type="hidden" name="contenttype" value="application/x-svgdraw">
`).appendTo('body')
.submit().remove();
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', saveSvgAction + '/' + name);
form.setAttribute('target', 'output_frame');
// eslint-disable-next-line no-unsanitized/property
form.innerHTML = `<input type="hidden" name="png_data" value="${pngData}">
<input type="hidden" name="filepath" value="${svgData}">
<input type="hidden" name="filename" value="drawing.svg">
<input type="hidden" name="contenttype" value="application/x-svgdraw">`;
document.body.append(form);
form.submit();
form.remove();
// eslint-disable-next-line no-alert
alert(strings.saved);
top.window.location = '/' + name;

View File

@@ -63,14 +63,16 @@ export default {
if (avoidClientSide || avoidClientSideDownload) {
return false;
}
const support = $('<a>')[0].download === '';
const support = document.querySelector('a').download === '';
let a;
if (support) {
a = $('<a>hidden</a>').attr({
download: (filename || 'image') + suffix,
href: uri
}).css('display', 'none').appendTo('body');
a[0].click();
a = document.createElement("a");
a.text = 'hidden';
a.download = (filename || 'image') + suffix;
a.href = uri;
a.style.dispaly = 'none';
document.body.appendChild(a);
a.click();
return true;
}
return false;
@@ -84,10 +86,13 @@ export default {
// Hiding by size instead of display to avoid FF console errors
// with `getBBox` in browser.js `supportsPathBBox_`)
$(
`<iframe name="output_frame" title="${strings.hiddenframe}"
style="width: 0; height: 0;" src="data:text/html;base64,PGh0bWw+"/>`
).appendTo('body');
const iframe = document.createElement('IFRAME');
iframe.src="data:text/html;base64,PGh0bWw+";
document.body.append(iframe);
iframe.name = "output_frame";
iframe.contentWindow.document.title = strings.hiddenframe;
iframe.style.cssText = "width:0;height:0;";
svgEditor.setCustomHandlers({
save (win, data) {
const svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, // Firefox doesn't seem to know it is UTF-8 (no matter whether we use or skip the clientDownload code) despite the Content-Disposition header containing UTF-8, but adding the encoding works
@@ -97,15 +102,16 @@ export default {
return;
}
$('<form>').attr({
method: 'post',
action: saveSvgAction,
target: 'output_frame'
}).append(`
<input type="hidden" name="output_svg" value="${xhtmlEscape(svg)}">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">
`).appendTo('body')
.submit().remove();
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', saveSvgAction);
form.setAttribute('target', 'output_frame');
// eslint-disable-next-line no-unsanitized/property
form.innerHTML = `<input type="hidden" name="output_svg" value="${xhtmlEscape(svg)}">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">`;
document.body.append(form);
form.submit();
form.remove();
},
exportPDF (win, data) {
const filename = getFileNameFromTitle(),
@@ -113,28 +119,32 @@ export default {
if (clientDownloadSupport(filename, '.pdf', datauri)) {
return;
}
$('<form>').attr({
method: 'post',
action: saveImgAction,
target: 'output_frame'
}).append(`
<input type="hidden" name="output_img" value="${datauri}">
<input type="hidden" name="mime" value="application/pdf">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">
`).appendTo('body')
.submit().remove();
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', saveImgAction);
form.setAttribute('target', 'output_frame');
// eslint-disable-next-line no-unsanitized/property
form.innerHTML = `<input type="hidden" name="output_img" value="${datauri}">
<input type="hidden" name="mime" value="application/pdf">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">`;
document.body.append(form);
form.submit();
form.remove();
},
// Todo: Integrate this extension with a new built-in exportWindowType, "download"
async exportImage (win, data) {
const {issues, mimeType, quality} = data;
if (!$('#export_canvas').length) {
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
if (!$id('export_canvas')) {
const canvasx = document.createElement("CANVAS");
canvasx.id = 'export_canvas';
canvasx.style.display = 'none';
document.body.appendChild(canvasx);
}
const c = $('#export_canvas')[0];
const c = $id('export_canvas');
c.width = svgCanvas.contentW;
c.height = svgCanvas.contentH;
c.style.width = svgCanvas.contentW;
c.style.height = svgCanvas.contentH;
await canvg(c, data.svg);
const datauri = quality ? c.toDataURL(mimeType, quality) : c.toDataURL(mimeType);
// {uiStrings} = svgEditor;
@@ -158,16 +168,17 @@ export default {
return;
}
$('<form>').attr({
method: 'post',
action: saveImgAction,
target: 'output_frame'
}).append(`
<input type="hidden" name="output_img" value="${datauri}">
<input type="hidden" name="mime" value="${mimeType}">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">
`).appendTo('body')
.submit().remove();
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', saveImgAction);
form.setAttribute('target', 'output_frame');
// eslint-disable-next-line no-unsanitized/property
form.innerHTML = `<input type="hidden" name="output_img" value="${datauri}">
<input type="hidden" name="mime" value="${mimeType}">
<input type="hidden" name="filename" value="${xhtmlEscape(filename)}">`;
document.body.append(form);
form.submit();
form.remove();
}
});
@@ -209,19 +220,21 @@ export default {
};
// Create upload form
const openSvgForm = $('<form>');
openSvgForm.attr({
enctype: 'multipart/form-data',
method: 'post',
action: openSvgAction,
target: 'output_frame'
});
const openSvgForm = document.createElement("FORM");
openSvgForm.action = openSvgAction;
openSvgForm.enctype = 'multipart/form-data';
openSvgForm.method = 'post';
openSvgForm.target = 'output_frame';
// Create import form
const importSvgForm = openSvgForm.clone().attr('action', importSvgAction);
const importSvgForm = openSvgForm.cloneNode(true);
importSvgForm.action = importSvgAction;
// Create image form
const importImgForm = openSvgForm.clone().attr('action', importImgAction);
const importImgForm = openSvgForm.cloneNode(true);
importImgForm.action = importImgAction;
// It appears necessary to rebuild this input every time a file is
// selected so the same file can be picked and the change event can fire.
@@ -233,7 +246,10 @@ export default {
*/
function rebuildInput (form) {
form.empty();
const inp = $('<input type="file" name="svg_file">').appendTo(form);
const inp = document.createElement('input');
inp.type = 'file';
inp.name = 'svg_file';
form.appendChild(inp);
/**
* Submit the form, empty its contents for reuse and show
@@ -276,8 +292,8 @@ export default {
// Add forms to buttons
$id("tool_open").style.display = 'block';
$id("tool_import").style.display = 'block';
$('#tool_open').prepend(openSvgForm);
$('#tool_import').prepend(importSvgForm);
$('#tool_image').prepend(importImgForm);
$id('tool_open').insertBefore(openSvgForm, $id('tool_open').firstChild);
$id('tool_import').insertBefore(importSvgForm, $id('tool_import').firstChild);
$id('tool_image').insertBefore(importImgForm, $id('tool_image').firstChild);
}
};

View File

@@ -25,16 +25,9 @@ export default {
const {svgCanvas} = svgEditor;
const {$id} = svgCanvas;
const {$} = S; // {svgcontent},
let
selElems,
// editingitex = false,
// svgdoc = S.svgroot.parentNode.ownerDocument,
started,
newFO;
// edg = 0,
// newFOG, newFOGParent, newDef, newImageName, newMaskID,
// undoCommand = 'Not image',
// modeChangeG, ccZoom, wEl, hEl, wOffset, hOffset, ccRgbEl, brushW, brushH;
let selElems;
let started;
let newFO;
const strings = await loadExtensionTranslation(svgEditor.configObj.pref('lang'));
/**
@@ -42,93 +35,73 @@ export default {
* @param {boolean} on
* @returns {void}
*/
function showPanel (on) {
let fcRules = $('#fc_rules');
if (!fcRules.length) {
fcRules = $('<style id="fc_rules"></style>').appendTo('head');
}
fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#star_panel').toggle(on);
const showPanel = (on) => {
$id('star_panel').style.display = (on) ? 'block' : 'none';
}
/*
function toggleSourceButtons(on){
$('#star_save, #star_cancel').toggle(on);
}
*/
/**
*
* @param {string} attr
* @param {string|Float} val
* @returns {void}
*/
function setAttr (attr, val) {
const setAttr = (attr, val) => {
svgCanvas.changeSelectedAttribute(attr, val);
svgCanvas.call('changed', selElems);
}
/*
function cot(n){
return 1 / Math.tan(n);
}
function sec(n){
return 1 / Math.cos(n);
}
*/
const events = {
id: 'tool_star',
click () {
showPanel(true);
svgCanvas.setMode('star');
}
};
const contextTools = [{
type: 'input',
panel: 'star_panel',
id: 'starNumPoints',
size: 3,
defval: 5,
events: {
change () {
setAttr('point', this.value);
}
}
}, {
type: 'input',
panel: 'star_panel',
id: 'starRadiusMulitplier',
size: 3,
defval: 2.5
}, {
type: 'input',
panel: 'star_panel',
id: 'radialShift',
size: 3,
defval: 0,
events: {
change () {
setAttr('radialshift', this.value);
}
}
}];
return {
name: strings.name,
events,
context_tools: strings.contextTools.map((contextTool, i) => {
return Object.assign(contextTools[i], contextTool);
}),
// The callback should be used to load the DOM with the appropriate UI items
callback () {
if($id("star_panel") !== null) $id("star_panel").style.display = 'none';
// const endChanges = function(){};
// Add the button and its handler(s)
// Note: the star extension may also add the same flying button so we check first
if ($id('tools_polygon') === null) {
const buttonTemplate = document.createElement("template");
buttonTemplate.innerHTML = `
<se-flyingbutton id="tools_polygon" title="Polygone/Star Tool">
<se-button id="tool_polygon" title="Polygon Tool" src="./images/polygon.svg"></se-button>
<se-button id="tool_star" title="Star Tool" src="./images/star.svg"></se-button>
</se-flyingbutton>
`
$id('tools_left').append(buttonTemplate.content.cloneNode(true));
}
$id('tool_star').addEventListener("click", () => { showPanel(true);
if (this.leftPanel.updateLeftPanel('tool_polygon')) {
svgCanvas.setMode('star');
showPanel(true);
}
});
// Add the context panel and its handler(s)
const panelTemplate = document.createElement("template");
panelTemplate.innerHTML = `
<div id="star_panel">
<se-spin-input id="starNumPoints" label="points" min=1 step=1 value=5 title="Change rotation angle">
</se-spin-input>
<se-spin-input id="RadiusMultiplier" label="Radis multiplier" min=1 step=2.5 value=5 title="Change rotation angle">
</se-spin-input>
<se-spin-input id="radialShift" min=0 step=1 value=0 label="radial shift" title="Change rotation angle">
</se-spin-input>
</div>
`
//add handlers for the panel
$id('tools_top').appendChild(panelTemplate.content.cloneNode(true));
$id("starNumPoints").addEventListener("change", (event) => {
setAttr('point', event.target.value);
});
$id("RadiusMultiplier").addEventListener("change", (event) => {
setAttr('starRadiusMultiplier', event.target.value);
});
$id("radialShift").addEventListener("change", (event) => {
setAttr('radialshift', event.target.value);
});
// don't display the star panel on start
$id("star_panel").style.display = 'none';
},
mouseDown (opts) {
const rgb = svgCanvas.getColor('fill');
// const ccRgbEl = rgb.substring(1, rgb.length);
const sRgb = svgCanvas.getColor('stroke');
// const ccSRgbEl = sRgb.substring(1, rgb.length);
const sWidth = svgCanvas.getStrokeWidth();
if (svgCanvas.getMode() === 'star') {
@@ -162,13 +135,20 @@ export default {
return undefined;
}
if (svgCanvas.getMode() === 'star') {
const c = $(newFO).attr(['cx', 'cy', 'point', 'orient', 'fill', 'strokecolor', 'strokeWidth', 'radialshift']);
const cx = Number(newFO.getAttribute('cx'));
const cy = Number(newFO.getAttribute('cy'));
const point = Number(newFO.getAttribute('point'));
const orient = newFO.getAttribute('orient');
const fill = newFO.getAttribute('fill');
const strokecolor = newFO.getAttribute('strokecolor');
const strokeWidth = Number(newFO.getAttribute('strokeWidth'));
const radialshift = Number(newFO.getAttribute('radialshift'));
let x = opts.mouse_x;
let y = opts.mouse_y;
const {cx, cy, fill, strokecolor, strokeWidth, radialshift, point, orient} = c,
circumradius = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5,
inradius = circumradius / document.getElementById('starRadiusMulitplier').value;
const circumradius = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5;
const inradius = circumradius / document.getElementById('RadiusMultiplier').value;
newFO.setAttribute('r', circumradius);
newFO.setAttribute('r2', inradius);
@@ -215,10 +195,9 @@ export default {
},
mouseUp () {
if (svgCanvas.getMode() === 'star') {
const attrs = $(newFO).attr(['r']);
// svgCanvas.addToSelection([newFO], true);
const r = newFO.getAttribute('r');
return {
keep: (attrs.r !== '0'),
keep: (r !== '0'),
element: newFO
};
}
@@ -233,9 +212,8 @@ export default {
const elem = selElems[i];
if (elem && elem.getAttribute('shape') === 'star') {
if (opts.selectedElement && !opts.multiselected) {
// $('#starRadiusMulitplier').val(elem.getAttribute('r2'));
$('#starNumPoints').val(elem.getAttribute('point'));
$('#radialShift').val(elem.getAttribute('radialshift'));
$id('starNumPoints').value = elem.getAttribute('point');
$id('radialShift').value = elem.getAttribute('radialshift');
showPanel(true);
} else {
showPanel(false);

View File

@@ -57,10 +57,6 @@ export default {
case 'view':
// Populate the contents
svgEditor.loadFromString(content);
/* if ($('#tool_save_file')) {
$('#tool_save_file').disabled = false;
} */
break;
case 'save-end':
// eslint-disable-next-line no-alert

View File

@@ -140,7 +140,6 @@ class BottomPanel {
* @type {module}
*/
handleOpacity (evt) {
// if ($(this).find('div').length) { return; }
const val = Number.parseInt(evt.currentTarget.value.split('%')[0]);
this.editor.svgCanvas.setOpacity(val / 100);
}

View File

@@ -1,6 +1,5 @@
/* eslint-disable max-len */
/* eslint-disable no-alert */
/* globals $ */
import SvgCanvas from "../../svgcanvas/svgcanvas.js";
const SIDEPANEL_MAXWIDTH = 300;
@@ -324,7 +323,6 @@ class LayersPanel {
* @returns {void}
*/
layerRename() {
// const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
const oldName = document.querySelector("#layerlist tr.layersel td.layername").textContent;
const newName = prompt(this.uiStrings.notification.enterNewLayerName, "");
if (!newName) {
@@ -375,58 +373,73 @@ class LayersPanel {
*/
populateLayers() {
this.editor.svgCanvas.clearSelection();
const layerlist = $("#layerlist tbody").empty();
const selLayerNames = $("#selLayerNames").empty();
const self = this;
const layerlist = $id("layerlist").querySelector('tbody');
while(layerlist.firstChild)
layerlist.removeChild(layerlist.firstChild);
const selLayerNames = $id("selLayerNames");
// empty() ref: http://youmightnotneedjquery.com/#empty
while(selLayerNames.firstChild)
selLayerNames.removeChild(selLayerNames.firstChild);
const drawing = this.editor.svgCanvas.getCurrentDrawing();
const currentLayerName = drawing.getCurrentLayerName();
let layer = this.editor.svgCanvas.getCurrentDrawing().getNumLayers();
// we get the layers in the reverse z-order (the layer rendered on top is listed first)
while (layer--) {
const name = drawing.getLayerName(layer);
const layerTr = $('<tr class="layer">').toggleClass(
"layersel",
name === currentLayerName
);
const layerVis = $('<td class="layervis">').toggleClass(
"layerinvis",
!drawing.getLayerVisibility(name)
);
const layerName = $('<td class="layername">' + name + "</td>");
layerlist.append(layerTr.append(layerVis, layerName));
selLayerNames.append(
'<option value="' + name + '">' + name + "</option>"
);
const layerTr = document.createElement("tr");
layerTr.className = (name === currentLayerName) ? 'layer layersel' : 'layer';
const layerVis = document.createElement("td");
layerVis.className = (!drawing.getLayerVisibility(name)) ? "layerinvis layervis" : 'layervis';
const layerName = document.createElement("td");
layerName.className = 'layername';
layerName.textContent = name;
layerTr.appendChild(layerVis);
layerTr.appendChild(layerName);
layerlist.appendChild(layerTr);
// eslint-disable-next-line no-unsanitized/property
selLayerNames.innerHTML += '<option value="' + name + '">' + name + '</option>';
}
// handle selection of layer
$("#layerlist td.layername")
.mouseup(evt => {
$("#layerlist tr.layer").removeClass("layersel");
$(evt.currentTarget.parentNode).addClass("layersel");
this.editor.svgCanvas.setCurrentLayer(evt.currentTarget.textContent);
evt.preventDefault();
})
.mouseover(evt => {
this.toggleHighlightLayer(
this.editor.svgCanvas,
const nelements = $id('layerlist').querySelectorAll("td.layername");
Array.from(nelements).forEach(function(element) {
element.addEventListener('mouseup', function(evt) {
const trElements = $id('layerlist').querySelectorAll("tr.layer");
Array.from(trElements).forEach(function(element) {
element.classList.remove("layersel");
});
evt.currentTarget.parentNode.classList.add("layersel");
self.editor.svgCanvas.setCurrentLayer(evt.currentTarget.textContent);
evt.preventDefault();
});
element.addEventListener('mouseup', function(evt) {
self.toggleHighlightLayer(
self.editor.svgCanvas,
evt.currentTarget.textContent
);
})
.mouseout(() => {
this.toggleHighlightLayer(this.editor.svgCanvas);
});
$("#layerlist td.layervis").click(evt => {
const row = $(evt.currentTarget.parentNode).prevAll().length;
const name = $("#layerlist tr.layer:eq(" + row + ") td.layername").text();
const vis = $(evt.currentTarget).hasClass("layerinvis");
this.editor.svgCanvas.setLayerVisibility(name, vis);
$(evt.currentTarget).toggleClass("layerinvis");
element.addEventListener('mouseout', function(evt) {
self.toggleHighlightLayer(self.editor.svgCanvas);
});
});
const elements = $id('layerlist').querySelectorAll("td.layervis");
Array.from(elements).forEach(function(element) {
element.addEventListener('click', function(evt) {
const name = evt.currentTarget.parentNode.querySelector("td.layername").textContent;
const vis = evt.currentTarget.classList.contains("layerinvis");
self.editor.svgCanvas.setLayerVisibility(name, vis);
evt.currentTarget.classList.toggle("layerinvis");
});
});
// if there were too few rows, let's add a few to make it not so lonely
let num = 5 - $("#layerlist tr.layer").size();
let num = 5 - $id('layerlist').querySelectorAll("tr.layer").length;
while (num-- > 0) {
// TODO: there must a better way to do this
layerlist.append('<tr><td style="color:white">_</td><td/></tr>');
const tlayer = document.createElement("tr");
tlayer.innerHTML = '<td style="color:white">_</td><td/>';
layerlist.append(tlayer);
}
}
}

View File

@@ -214,10 +214,6 @@ class LeftPanel {
<se-button id="tool_circle" title="Square" src="./images/circle.svg"></se-button>
<se-button id="tool_fhellipse" title="Free-Hand Rectangle" src="./images/fh_ellipse.svg"></se-button>
</se-flyingbutton>
<se-flyingbutton id="tools_polygon" title="Polygone/Star Tool">
<se-button id="tool_polygon" title="Polygon Tool" src="./images/polygon.svg"></se-button>
<se-button id="tool_star" title="Star Tool" src="./images/star.svg"></se-button>
</se-flyingbutton>
<se-button id="mode_connect" title="Connect two objects" src="./images/conn.svg"></se-button>
<se-button id="tool_text" title="Text Tool" src="./images/text.svg" shortcut="T"></se-button>
<se-button id="tool_image" title="Image Tool" src="./images/image.svg"></se-button>

View File

@@ -1,4 +1,3 @@
/* globals $ */
import SvgCanvas from "../../svgcanvas/svgcanvas.js";
import { isValidUnit, getTypeMap, convertUnit } from "../../common/units.js";
@@ -51,7 +50,13 @@ class TopPanel {
if (changeElem) {
this.svgCanvas.setStrokeAttr('stroke-' + pre, val);
}
$(opt).addClass('current').siblings().removeClass('current');
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');
});
}
/**
@@ -149,7 +154,7 @@ class TopPanel {
updateContextPanel() {
const setInputWidth = elem => {
const w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300);
$(elem).width(w);
elem.style.width = w + 'px';
};
let elem = this.editor.selectedElement;
@@ -182,14 +187,9 @@ class TopPanel {
$id("a_panel").style.display = 'none';
if (!isNullish(elem)) {
const elname = elem.nodeName;
// If this is a link with no transform and one child, pretend
// its child is selected
// if (elname === 'a') { // && !$(elem).attr('transform')) {
// elem = elem.firstChild;
// }
const angle = this.editor.svgCanvas.getRotationAngle(elem);
$("#angle").val(angle);
$id("angle").value = angle;
const blurval = this.editor.svgCanvas.getBlur(elem) * 10;
$id("blur").value = blurval;
@@ -227,8 +227,8 @@ class TopPanel {
y = convertUnit(y);
}
$("#selected_x").val(x || 0);
$("#selected_y").val(y || 0);
$id("selected_x").value = (x || 0);
$id("selected_y").value = (y || 0);
$id("xy_panel").style.display = 'block';
}
@@ -242,32 +242,31 @@ class TopPanel {
].includes(elname)
? "none"
: "block";
$id("tool_reorient").style.display =
elname === "path" ? "block" : "none";
$id("tool_reorient").disabled = angle === 0;
$id("tool_reorient").style.display = (elname === "path") ? "block" : "none";
$id("tool_reorient").disabled = (angle === 0);
} else {
const point = this.path.getNodePoint();
$("#tool_add_subpath").pressed = false;
$("#tool_node_delete").toggleClass(
"disabled",
!this.path.canDeleteNodes
);
$id("tool_add_subpath").pressed = false;
// eslint-disable-next-line max-len
(!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 = $("#seg_type");
const segType = $id("seg_type");
if (unit) {
point.x = convertUnit(point.x);
point.y = convertUnit(point.y);
}
$("#path_node_x").val(point.x);
$("#path_node_y").val(point.y);
$id("path_node_x").value = (point.x);
$id("path_node_y").value = (point.y);
if (point.type) {
segType.val(point.type).removeAttr("disabled");
segType.value = (point.type);
segType.removeAttribute("disabled");
} else {
segType.val(4).attr("disabled", "disabled");
segType.value = 4;
segType.setAttribute("disabled", "disabled");
}
}
return;
@@ -288,23 +287,23 @@ class TopPanel {
const { tagName } = elem;
// if ($(elem).data('gsvg')) {
// $('#g_panel').show();
// }
let linkHref = null;
if (tagName === "a") {
linkHref = this.editor.svgCanvas.getHref(elem);
$id("g_panel").style.display = 'block';
}
if (elem.parentNode.tagName === "a" && !$(elem).siblings().length) {
// siblings
const selements = Array.prototype.filter.call(elem.parentNode.children, function(child){
return child !== elem;
});
if (elem.parentNode.tagName === "a" && !selements.length) {
$id("a_panel").style.display = 'block';
linkHref = this.editor.svgCanvas.getHref(elem.parentNode);
}
// Hide/show the make_link buttons
$("#tool_make_link, #tool_make_link_multi").toggle(!linkHref);
$id('tool_make_link').style.display = (!linkHref) ? 'block' : 'none';
$id('tool_make_link_multi').style.display = (!linkHref) ? 'block' : 'none';
if (linkHref) {
$id("link_url").value = linkHref;
@@ -353,9 +352,8 @@ class TopPanel {
if (this.editor.svgCanvas.addedNew) {
// Timeout needed for IE9
setTimeout(() => {
$("#text")
.focus()
.select();
$id("text").focus()
$id("text").select();
}, 100);
}
// text
@@ -370,10 +368,10 @@ class TopPanel {
} else if (tagName === "g" || tagName === "use") {
$id("container_panel").style.display = 'block';
const title = this.editor.svgCanvas.getTitle();
const label = $("#g_title")[0];
const label = $id("g_title");
label.value = title;
setInputWidth(label);
$("#g_title").prop("disabled", tagName === "use");
$id("g_title").disabled = (tagName === "use");
}
}
menuItems.setAttribute(
@@ -408,9 +406,8 @@ class TopPanel {
if ((elem && !isNode) || this.multiselected) {
// update the selected elements' layer
$("#selLayerNames")
.removeAttr("disabled")
.val(currentLayerName);
$id("selLayerNames").removeAttribute("disabled")
$id("selLayerNames").value = currentLayerName;
// Enable regular menu options
const canCMenu = document.getElementById("se-cmenu_canvas");
@@ -419,7 +416,7 @@ class TopPanel {
"#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back"
);
} else {
$("#selLayerNames").attr("disabled", "disabled");
$id("selLayerNames").disabled = "disabled";
}
}
/**
@@ -444,13 +441,14 @@ class TopPanel {
$id("tool_wireframe").pressed = !$id("tool_wireframe").pressed;
this.editor.workarea.classList.toggle("wireframe");
const wfRules = $("#wireframe_rules");
if (!wfRules.length) {
/* wfRules = */ $('<style id="wireframe_rules"></style>').appendTo(
"head"
);
const wfRules = $id("wireframe_rules");
if (!wfRules) {
const fcRules = document.createElement('style');
fcRules.setAttribute('id', 'wireframe_rules');
document.getElementsByTagName("head")[0].appendChild(fcRules);
} else {
wfRules.empty();
while(wfRules.firstChild)
wfRules.removeChild(wfRules.firstChild);
}
this.editor.updateWireFrame();
}
@@ -496,10 +494,8 @@ class TopPanel {
*/
changeRotationAngle(e) {
this.editor.svgCanvas.setRotationAngle(e.target.value);
$("#tool_reorient").toggleClass(
"disabled",
Number.parseInt(e.target.value) === 0
);
// eslint-disable-next-line max-len
(Number.parseInt(e.target.value) === 0) ? $id("tool_reorient").classList.add("disabled") : $id("tool_reorient").classList.remove("disabled");
}
/**
@@ -544,7 +540,7 @@ class TopPanel {
* @returns {void}
*/
clickAlign(pos) {
let value = $("#tool_align_relative").val();
let value = $id("tool_align_relative").value;
if (value === "") {
value = "selected";
}
@@ -666,8 +662,8 @@ class TopPanel {
* @returns {void}
*/
addSubPath() {
const button = $("#tool_add_subpath");
const sp = !button.hasClass("pressed");
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);
@@ -752,7 +748,6 @@ class TopPanel {
<div class="tool_sep"></div>
<se-button id="tool_source" title="Edit Source" shortcut="U" src="./images/source.svg"></se-button>
<se-button id="tool_wireframe" title="Wireframe Mode" shortcut="F" src="./images/wireframe.svg"></se-button>
<se-button id="view_grid" title="Show grid" src="./images/grid.svg"></se-button>
</div> <!-- editor_panel -->
<div id="history_panel">
<div class="tool_sep"></div>