- Fix: Avoid extension includeWith button conflicts/redundancies;

Incorporates #147
- Fix: Ensure shift-key cycling through flyouts works with extension-added
    `includeWith` as well as toolbarbuttons
- Fix: Apply flyout arrows after extensions callback
- Fix: Ensure SVG icon of flyout right-arrow is cloned to can be applied to
    more than one extension
- Fix: Ensure line tool shows as selected when "L" key command is used
- Refactoring: Avoid passing on `undefined` var. (#147)
- Refactoring: lbs; avoid indent in connector, destructuring, use map over push
- Docs: Clarify nature of fixes
- Docs: JSDoc for `setupFlyouts`, `Actions`, `toggleSidePanel`; missing for
  ToolbarButton
This commit is contained in:
Brett Zamir
2018-07-26 16:41:38 -07:00
parent b4d7b221e0
commit 0a2da503f1
4 changed files with 209 additions and 136 deletions

View File

@@ -1,12 +1,25 @@
# 3.0.0-rc.2 # 3.0.0-rc.2
- Fix: Regression for `text` and `tspan` elements as far as - Fix: Avoid extension `includeWith` button conflicts/redundancies;
Incorporates #147
- Fix: Ensure shift-key cycling through flyouts works with extension-added
`includeWith` as well as toolbarbuttons
- Fix: Apply flyout arrows after extensions callback
- Fix: Ensure SVG icon of flyout right-arrow is cloned to can be applied to
more than one extension
- Fix: Ensure line tool shows as selected when "L" key command is used
- Fix (canvg): Regression for `text` and `tspan` elements as far as
`captureTextNodes` with canvg (inheriting class had set `captureTextNodes` with canvg (inheriting class had set
`captureTextNodes` too late) `captureTextNodes` too late)
- Fix: Avoid errors for tspan passed to `getGradient` - Fix (canvg): Avoid errors for `tspan` passed to `getGradient`
- i18n: picking stroke/fill paint and opacity - i18n: picking stroke/fill paint and opacity
- Optimize: Avoid rewriting `points` attribute for free-hand path; - Optimize: Avoid rewriting `points` attribute for free-hand path;
incorporates #176 (fixes #175) incorporates #176 (fixes #175)
- Refactoring: Avoid passing on `undefined` var. (#147)
- Refactoring: lbs; avoid indent in connector, destructuring, use map over push
- Docs: Clarify nature of fixes
- Docs: JSDoc for `setupFlyouts`, `Actions`, `toggleSidePanel`; missing for
ToolbarButton
# 3.0.0-rc.1 # 3.0.0-rc.1

View File

@@ -431,73 +431,74 @@ export default {
// , y = opts.mouse_y / zoom, // , y = opts.mouse_y / zoom,
let mouseTarget = e.target; let mouseTarget = e.target;
if (svgCanvas.getMode() === 'connector') { if (svgCanvas.getMode() !== 'connector') {
const fo = $(mouseTarget).closest('foreignObject'); return;
if (fo.length) { mouseTarget = fo[0]; } }
const fo = $(mouseTarget).closest('foreignObject');
if (fo.length) { mouseTarget = fo[0]; }
const parents = $(mouseTarget).parents(); const parents = $(mouseTarget).parents();
if (mouseTarget === startElem) { if (mouseTarget === startElem) {
// Start line through click // Start line through click
started = true; started = true;
return {
keep: true,
element: null,
started
};
}
if ($.inArray(svgcontent, parents) === -1) {
// Not a valid target element, so remove line
$(curLine).remove();
started = false;
return {
keep: false,
element: null,
started
};
}
// Valid end element
endElem = mouseTarget;
const startId = startElem.id, endId = endElem.id;
const connStr = startId + ' ' + endId;
const altStr = endId + ' ' + startId;
// Don't create connector if one already exists
const dupe = $(svgcontent).find(connSel).filter(function () {
const conn = this.getAttributeNS(seNs, 'connector');
if (conn === connStr || conn === altStr) { return true; }
});
if (dupe.length) {
$(curLine).remove();
return {
keep: false,
element: null,
started: false
};
}
const bb = svgCanvas.getStrokedBBox([endElem]);
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);
seNs = svgCanvas.getEditorNS(true);
curLine.setAttributeNS(seNs, 'se:connector', connStr);
curLine.setAttribute('class', connSel.substr(1));
curLine.setAttribute('opacity', 1);
svgCanvas.addToSelection([curLine]);
svgCanvas.moveToBottomSelectedElement();
selManager.requestSelector(curLine).showGrips(false);
started = false;
return { return {
keep: true, keep: true,
element: curLine, element: null,
started started
}; };
} }
if ($.inArray(svgcontent, parents) === -1) {
// Not a valid target element, so remove line
$(curLine).remove();
started = false;
return {
keep: false,
element: null,
started
};
}
// Valid end element
endElem = mouseTarget;
const startId = startElem.id, endId = endElem.id;
const connStr = startId + ' ' + endId;
const altStr = endId + ' ' + startId;
// Don't create connector if one already exists
const dupe = $(svgcontent).find(connSel).filter(function () {
const conn = this.getAttributeNS(seNs, 'connector');
if (conn === connStr || conn === altStr) { return true; }
});
if (dupe.length) {
$(curLine).remove();
return {
keep: false,
element: null,
started: false
};
}
const bb = svgCanvas.getStrokedBBox([endElem]);
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);
seNs = svgCanvas.getEditorNS(true);
curLine.setAttributeNS(seNs, 'se:connector', connStr);
curLine.setAttribute('class', connSel.substr(1));
curLine.setAttribute('opacity', 1);
svgCanvas.addToSelection([curLine]);
svgCanvas.moveToBottomSelectedElement();
selManager.requestSelector(curLine).showGrips(false);
started = false;
return {
keep: true,
element: curLine,
started
};
}, },
selectedChanged (opts) { selectedChanged (opts) {
// TODO: Find better way to skip operations if no connectors are in use // TODO: Find better way to skip operations if no connectors are in use

View File

@@ -814,6 +814,11 @@ editor.init = function () {
*/ */
(win, data) => { (win, data) => {
extensionsAdded = true; extensionsAdded = true;
Actions.setAll();
$('.flyout_arrow_horiz:empty').each(function () {
$(this).append($.getSvgIcon('arrow_right', true).width(5).height(5));
});
messageQueue.forEach( messageQueue.forEach(
/** /**
* @param {module:svgcanvas.SvgCanvas#event:message} messageObj * @param {module:svgcanvas.SvgCanvas#event:message} messageObj
@@ -837,9 +842,9 @@ editor.init = function () {
const setFlyoutPositions = function () { const setFlyoutPositions = function () {
$('.tools_flyout').each(function () { $('.tools_flyout').each(function () {
const shower = $('#' + this.id + '_show'); const shower = $('#' + this.id + '_show');
const pos = shower.offset(); const {left, top} = shower.offset();
const w = shower.outerWidth(); const w = shower.outerWidth();
$(this).css({left: (pos.left + w) * editor.tool_scale, top: pos.top}); $(this).css({left: (left + w) * editor.tool_scale, top});
}); });
}; };
@@ -1327,12 +1332,6 @@ editor.init = function () {
}}).then(() => { }}).then(() => {
$('#svg_container')[0].style.visibility = 'visible'; $('#svg_container')[0].style.visibility = 'visible';
editor.runCallbacks(); editor.runCallbacks();
setTimeout(function () {
$('.flyout_arrow_horiz:empty').each(function () {
$(this).append($.getSvgIcon('arrow_right').width(5).height(5));
});
}, 1);
}); });
} }
}); });
@@ -2696,46 +2695,68 @@ editor.init = function () {
return; return;
} }
const tooltips = []; const tooltips = $(this).children().map(function () {
$(this).children().each(function () { return this.title;
tooltips.push(this.title); }).get();
});
shower[0].title = tooltips.join(' / '); shower[0].title = tooltips.join(' / ');
}); });
}; };
const allHolders = {};
/**
* @param {Object.<string, module:SVGEditor.ToolButton>} holders Key is a selector
* @returns {undefined}
*/
const setupFlyouts = function (holders) { const setupFlyouts = function (holders) {
$.each(holders, function (holdSel, btnOpts) { $.each(holders, function (holdSel, btnOpts) {
const buttons = $(holdSel).children(); if (!allHolders[holdSel]) {
allHolders[holdSel] = [];
}
allHolders[holdSel].push(...btnOpts);
const buttons = $(holdSel).children().not('.tool_button_evt_handled');
const showSel = holdSel + '_show'; const showSel = holdSel + '_show';
const shower = $(showSel); const shower = $(showSel);
let def = false; let def = false;
buttons.addClass('tool_button') buttons.addClass('tool_button tool_button_evt_handled')
.unbind('click mousedown mouseup') // may not be necessary .unbind('click mousedown mouseup') // may not be necessary
.each(function (i) { .each(function () {
// Get this buttons options // Get this button's options
const opts = btnOpts[i]; const idSel = '#' + this.getAttribute('id');
const [i, opts] = Object.entries(btnOpts).find(([i, {sel}]) => {
return sel === idSel;
});
// Remember the function that goes with this ID // Remember the function that goes with this ID
flyoutFuncs[opts.sel] = opts.fn; flyoutFuncs[opts.sel] = opts.fn;
if (opts.isDefault) { def = i; } if (opts.isDefault) { def = i; }
// Clicking the icon in flyout should set this set's icon /**
const func = function (event) { * Clicking the icon in flyout should set this set's icon
* @param {Event} ev
* @returns {undefined}
*/
const flyoutAction = function (ev) {
let options = opts; let options = opts;
// Find the currently selected tool if comes from keystroke // Find the currently selected tool if comes from keystroke
if (event.type === 'keydown') { if (ev.type === 'keydown') {
const flyoutIsSelected = $(options.parent + '_show').hasClass('tool_button_current'); const flyoutIsSelected = $(options.parent + '_show').hasClass('tool_button_current');
const currentOperation = $(options.parent + '_show').attr('data-curopt'); const currentOperation = $(options.parent + '_show').attr('data-curopt');
$.each(holders[opts.parent], function (i, tool) { Object.entries(holders[opts.parent]).some(([i, tool]) => {
if (tool.sel === currentOperation) { if (tool.sel !== currentOperation) {
if (!event.shiftKey || !flyoutIsSelected) { return;
options = tool;
} else {
options = holders[opts.parent][i + 1] || holders[opts.parent][0];
}
} }
if (!ev.shiftKey || !flyoutIsSelected) {
options = tool;
} else {
// If flyout is selected, allow shift key to iterate through subitems
i = parseInt(i, 10);
// Use `allHolders` to include both extension `includeWith` and toolbarButtons
options = allHolders[opts.parent][i + 1] ||
holders[opts.parent][0];
}
return true;
}); });
} }
if ($(this).hasClass('disabled')) { return false; } if ($(this).hasClass('disabled')) { return false; }
@@ -2755,10 +2776,10 @@ editor.init = function () {
shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode
}; };
$(this).mouseup(func); $(this).mouseup(flyoutAction);
if (opts.key) { if (opts.key) {
$(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], func); $(document).bind('keydown', opts.key[0] + ' shift+' + opts.key[0], flyoutAction);
} }
}); });
@@ -2884,7 +2905,7 @@ editor.init = function () {
* @param {external:Window} win * @param {external:Window} win
* @param {module:svgcanvas.SvgCanvas#event:extension_added} ext * @param {module:svgcanvas.SvgCanvas#event:extension_added} ext
* @listens module:svgcanvas.SvgCanvas#event:extension_added * @listens module:svgcanvas.SvgCanvas#event:extension_added
* @returns {undefined} * @returns {Promise} Resolves to `undefined`
*/ */
const extAdded = function (win, ext) { const extAdded = function (win, ext) {
if (!ext) { if (!ext) {
@@ -3040,8 +3061,9 @@ editor.init = function () {
/** /**
* @typedef {GenericArray} module:SVGEditor.KeyArray * @typedef {GenericArray} module:SVGEditor.KeyArray
* @property {string} 0 * @property {string} 0 The key to bind (on `keydown`)
* @property {boolean} 1 Whether to `preventDefault` on the `keydown` event * @property {boolean} 1 Whether to `preventDefault` on the `keydown` event
* @property {boolean} 2 Not apparently in use (NoDisableInInput)
*/ */
/** /**
* @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key * @typedef {string|module:SVGEditor.KeyArray} module:SVGEditor.Key
@@ -3065,7 +3087,7 @@ editor.init = function () {
* @property {module:SVGEditor.Key} [key] The key to bind to the button * @property {module:SVGEditor.Key} [key] The key to bind to the button
*/ */
// Add buttons given by extension // Add buttons given by extension
$.each(ext.buttons, function (i, btn) { $.each(ext.buttons, function (i, /** @type {module:SVGEditor.Button} */ btn) {
let {id} = btn; let {id} = btn;
let num = i; let num = i;
// Give button a unique ID // Give button a unique ID
@@ -3159,7 +3181,7 @@ editor.init = function () {
icon: btn.id, icon: btn.id,
// key: btn.key, // key: btn.key,
isDefault: true isDefault: true
}, refData]; }]; // , refData
// //
// // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
// //
@@ -3202,7 +3224,6 @@ editor.init = function () {
.append($('<div>', {class: 'flyout_arrow_horiz'})); .append($('<div>', {class: 'flyout_arrow_horiz'}));
refBtn.before(showBtn); refBtn.before(showBtn);
// Create a flyout div // Create a flyout div
flyoutHolder = makeFlyoutHolder(tlsId, refBtn); flyoutHolder = makeFlyoutHolder(tlsId, refBtn);
} }
@@ -3220,7 +3241,7 @@ editor.init = function () {
fn: btn.events.click, fn: btn.events.click,
icon: btn.id, icon: btn.id,
key: btn.key, key: btn.key,
isDefault: btn.includeWith ? btn.includeWith.isDefault : 0 isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault)
}, refData]; }, refData];
// {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'} // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
@@ -3274,26 +3295,27 @@ editor.init = function () {
}); });
if (svgicons) { if (svgicons) {
$.svgIcons(svgicons, { return new Promise((resolve, reject) => {
w: 24, h: 24, $.svgIcons(svgicons, {
id_match: false, w: 24, h: 24,
no_img: (!isWebkit()), id_match: false,
fallback: fallbackObj, no_img: (!isWebkit()),
placement: placementObj, fallback: fallbackObj,
callback (icons) { placement: placementObj,
// Non-ideal hack to make the icon match the current size callback (icons) {
// if (curPrefs.iconsize && curPrefs.iconsize !== 'm') { // Non-ideal hack to make the icon match the current size
if ($.pref('iconsize') !== 'm') { // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
prepResize(); if ($.pref('iconsize') !== 'm') {
prepResize();
}
runCallback();
resolve();
} }
runCallback(); });
}
}); });
} }
} }
if (!svgicons) { return runCallback();
runCallback();
}
}; };
const getPaint = function (color, opac, type) { const getPaint = function (color, opac, type) {
@@ -4908,8 +4930,11 @@ editor.init = function () {
changeSidePanelWidth(deltaX); changeSidePanelWidth(deltaX);
}; };
// if width is non-zero, then fully close it, otherwise fully open it /**
// the optional close argument forces the side panel closed * If width is non-zero, then fully close it, otherwise fully open it
* @param {boolean} close Forces the side panel closed
* @returns {undefined}
*/
const toggleSidePanel = function (close) { const toggleSidePanel = function (close) {
const w = $('#sidepanels').width(); const w = $('#sidepanels').width();
const deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w; const deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w;
@@ -5023,19 +5048,43 @@ editor.init = function () {
// Prevent browser from erroneously repopulating fields // Prevent browser from erroneously repopulating fields
$('input,select').attr('autocomplete', 'off'); $('input,select').attr('autocomplete', 'off');
// Associate all button actions as well as non-button keyboard shortcuts /**
* Associate all button actions as well as non-button keyboard shortcuts
* @namespace {PlainObject} module:SVGEditor~Actions
*/
const Actions = (function () { const Actions = (function () {
// sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput] /**
* @typedef {PlainObject} module:SVGEditor.ToolButton
* @property {string} sel The CSS selector for the tool
* @property {external:jQuery.Function} fn A handler to be attached to the `evt`
* @property {string} evt The event for which the `fn` listener will be added
* @property {module:SVGEditor.Key} [key] [key, preventDefault, NoDisableInInput]
* @property {string} [parent] Selector
* @property {boolean} [hidekey] Whether to show key value in title
* @property {string} [icon] The button ID
* @property {boolean} isDefault For flyout holders
*/
/**
*
* @name module:SVGEditor~ToolButtons
* @type {module:SVGEditor.ToolButton[]}
*/
const toolButtons = [ const toolButtons = [
{sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]}, {sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]},
{sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]}, {sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]},
{sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true]}, {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true], parent: '#tools_line', prepend: true},
{sel: '#tool_rect', fn: clickRect, evt: 'mouseup', key: ['R', true], parent: '#tools_rect', icon: 'rect'}, {sel: '#tool_rect', fn: clickRect, evt: 'mouseup',
{sel: '#tool_square', fn: clickSquare, evt: 'mouseup', parent: '#tools_rect', icon: 'square'}, key: ['R', true], parent: '#tools_rect', icon: 'rect'},
{sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup', parent: '#tools_rect', icon: 'fh_rect'}, {sel: '#tool_square', fn: clickSquare, evt: 'mouseup',
{sel: '#tool_ellipse', fn: clickEllipse, evt: 'mouseup', key: ['E', true], parent: '#tools_ellipse', icon: 'ellipse'}, parent: '#tools_rect', icon: 'square'},
{sel: '#tool_circle', fn: clickCircle, evt: 'mouseup', parent: '#tools_ellipse', icon: 'circle'}, {sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup',
{sel: '#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup', parent: '#tools_ellipse', icon: 'fh_ellipse'}, parent: '#tools_rect', icon: 'fh_rect'},
{sel: '#tool_ellipse', fn: clickEllipse, evt: 'mouseup',
key: ['E', true], parent: '#tools_ellipse', icon: 'ellipse'},
{sel: '#tool_circle', fn: clickCircle, evt: 'mouseup',
parent: '#tools_ellipse', icon: 'circle'},
{sel: '#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup',
parent: '#tools_ellipse', icon: 'fh_ellipse'},
{sel: '#tool_path', fn: clickPath, evt: 'click', key: ['P', true]}, {sel: '#tool_path', fn: clickPath, evt: 'click', key: ['P', true]},
{sel: '#tool_text', fn: clickText, evt: 'click', key: ['T', true]}, {sel: '#tool_text', fn: clickText, evt: 'click', key: ['T', true]},
{sel: '#tool_image', fn: clickImage, evt: 'mouseup'}, {sel: '#tool_image', fn: clickImage, evt: 'mouseup'},
@@ -5053,13 +5102,15 @@ editor.init = function () {
{sel: '#tool_import', fn: clickImport, evt: 'mouseup'}, {sel: '#tool_import', fn: clickImport, evt: 'mouseup'},
{sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]}, {sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]},
{sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]}, {sel: '#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]},
{sel: '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel', fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true}, {sel: '#tool_source_cancel,.overlay,#tool_docprops_cancel,#tool_prefs_cancel',
fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true},
{sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click'}, {sel: '#tool_source_save', fn: saveSourceEditor, evt: 'click'},
{sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'}, {sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'},
{sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup'}, {sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup'},
{sel: '#tool_prefs_save', fn: savePreferences, evt: 'click'}, {sel: '#tool_prefs_save', fn: savePreferences, evt: 'click'},
{sel: '#tool_prefs_option', fn () { showPreferences(); return false; }, evt: 'mouseup'}, {sel: '#tool_prefs_option', fn () { showPreferences(); return false; }, evt: 'mouseup'},
{sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected, evt: 'click', key: ['del/backspace', true]}, {sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected,
evt: 'click', key: ['del/backspace', true]},
{sel: '#tool_reorient', fn: reorientPath, evt: 'click'}, {sel: '#tool_reorient', fn: reorientPath, evt: 'click'},
{sel: '#tool_node_link', fn: linkControlPoints, evt: 'click'}, {sel: '#tool_node_link', fn: linkControlPoints, evt: 'click'},
{sel: '#tool_node_clone', fn: clonePathNode, evt: 'click'}, {sel: '#tool_node_clone', fn: clonePathNode, evt: 'click'},
@@ -5131,7 +5182,10 @@ editor.init = function () {
'5/Shift+5': '#tools_ellipse_show' '5/Shift+5': '#tools_ellipse_show'
}; };
return { return { /** @lends module:SVGEditor~Actions */
/**
* @returns {undefined}
*/
setAll () { setAll () {
const flyouts = {}; const flyouts = {};
@@ -5154,8 +5208,10 @@ editor.init = function () {
if (!fH.length) { if (!fH.length) {
fH = makeFlyoutHolder(opts.parent.substr(1)); fH = makeFlyoutHolder(opts.parent.substr(1));
} }
if (opts.prepend) {
fH.append(btn); btn[0].style.margin = 'initial';
}
fH[opts.prepend ? 'prepend' : 'append'](btn);
if (!Array.isArray(flyouts[opts.parent])) { if (!Array.isArray(flyouts[opts.parent])) {
flyouts[opts.parent] = []; flyouts[opts.parent] = [];
@@ -5230,6 +5286,9 @@ editor.init = function () {
$('#tool_zoom').dblclick(dblclickZoom); $('#tool_zoom').dblclick(dblclickZoom);
}, },
/**
* @returns {undefined}
*/
setTitles () { setTitles () {
$.each(keyAssocs, function (keyval, sel) { $.each(keyAssocs, function (keyval, sel) {
const menu = ($(sel).parents('#main_menu').length); const menu = ($(sel).parents('#main_menu').length);
@@ -5260,18 +5319,18 @@ editor.init = function () {
}); });
}); });
}, },
/**
* @param {string} sel Selector to match
* @returns {module:SVGEditor.ToolButton}
*/
getButtonData (sel) { getButtonData (sel) {
let b; return Object.values(toolButtons).find((btn) => {
$.each(toolButtons, function (i, btn) { return btn.sel === sel;
if (btn.sel === sel) { b = btn; }
}); });
return b;
} }
}; };
}()); }());
Actions.setAll();
// Select given tool // Select given tool
editor.ready(function () { editor.ready(function () {
let tool; let tool;

View File

@@ -1156,7 +1156,7 @@ this.addExtension = async function (name, extInitFunc, importLocale) {
} }
extensions[name] = extObj; extensions[name] = extObj;
call('extension_added', extObj); return call('extension_added', extObj);
} else { } else {
console.log('Cannot add extension "' + name + '", an extension by that name already exists.'); console.log('Cannot add extension "' + name + '", an extension by that name already exists.');
} }