', {class: 'flyout_arrow_horiz'}));
refBtn.before(showBtn);
// Create a flyout div
flyoutHolder = makeFlyoutHolder(tlsId, refBtn);
+ flyoutHolder.data('isLibrary', true);
+ showBtn.data('isLibrary', true);
}
+ // refData = Actions.getButtonData(opts.button);
- refData = Actions.getButtonData(opts.button);
-
- if (opts.isDefault) {
- placementObj['#' + tlsId + '_show'] = btn.id;
- }
+ placementObj['#' + tlsId + '_show'] = btn.id;
// TODO: Find way to set the current icon using the iconloader if this is not default
// Include data for extension button as well as ref button
@@ -2733,2447 +2662,2530 @@ window.svgEditor = (function ($) {
sel: '#' + id,
fn: btn.events.click,
icon: btn.id,
- key: btn.key,
- isDefault: btn.includeWith ? btn.includeWith.isDefault : 0
+ // key: btn.key,
+ isDefault: true
}, refData];
+ //
+ // // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
+ //
+ // const pos = ('position' in opts)?opts.position:'last';
+ // const len = flyoutHolder.children().length;
+ //
+ // // Add at given position or end
+ // if (!isNaN(pos) && pos >= 0 && pos < len) {
+ // flyoutHolder.children().eq(pos).before(button);
+ // } else {
+ // flyoutHolder.append(button);
+ // curH.reverse();
+ // }
+ } else if (btn.type === 'app_menu') {
+ button.append('
').append(btn.title);
+ }
+ } else if (btn.list) {
+ // Add button to list
+ button.addClass('push_button');
+ $('#' + btn.list + '_opts').append(button);
+ if (btn.isDefault) {
+ $('#cur_' + btn.list).append(button.children().clone());
+ svgicon = btn.svgicon || btn.id;
+ placementObj['#cur_' + btn.list] = svgicon;
+ }
+ } else if (btn.includeWith) {
+ // Add to flyout menu / make flyout menu
+ const opts = btn.includeWith;
+ // opts.button, default, position
+ refBtn = $(opts.button);
- // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
+ flyoutHolder = refBtn.parent();
+ // Create a flyout menu if there isn't one already
+ if (!refBtn.parent().hasClass('tools_flyout')) {
+ // Create flyout placeholder
+ tlsId = refBtn[0].id.replace('tool_', 'tools_');
+ showBtn = refBtn.clone()
+ .attr('id', tlsId + '_show')
+ .append($('
', {class: 'flyout_arrow_horiz'}));
- var pos = ('position' in opts) ? opts.position : 'last';
- var len = flyoutHolder.children().length;
+ refBtn.before(showBtn);
- // Add at given position or end
- if (!isNaN(pos) && pos >= 0 && pos < len) {
- flyoutHolder.children().eq(pos).before(button);
- } else {
- flyoutHolder.append(button);
- curH.reverse();
- }
+ // Create a flyout div
+ flyoutHolder = makeFlyoutHolder(tlsId, refBtn);
}
- if (!svgicons) {
- button.append(icon);
- }
+ refData = Actions.getButtonData(opts.button);
- if (!btn.list) {
- // Add given events to button
- $.each(btn.events, function (name, func) {
- if (name === 'click' && btn.type === 'mode') {
- if (btn.includeWith) {
- button.bind(name, func);
- } else {
- button.bind(name, function () {
- if (toolButtonClick(button)) {
- func();
- }
- });
- }
- if (btn.key) {
- $(document).bind('keydown', btn.key, func);
- if (btn.title) {
- button.attr('title', btn.title + ' [' + btn.key + ']');
- }
- }
- } else {
+ if (opts.isDefault) {
+ placementObj['#' + tlsId + '_show'] = btn.id;
+ }
+ // TODO: Find way to set the current icon using the iconloader if this is not default
+
+ // Include data for extension button as well as ref button
+ curH = holders['#' + flyoutHolder[0].id] = [{
+ sel: '#' + id,
+ fn: btn.events.click,
+ icon: btn.id,
+ key: btn.key,
+ isDefault: btn.includeWith ? btn.includeWith.isDefault : 0
+ }, refData];
+
+ // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
+
+ const pos = ('position' in opts) ? opts.position : 'last';
+ const len = flyoutHolder.children().length;
+
+ // Add at given position or end
+ if (!isNaN(pos) && pos >= 0 && pos < len) {
+ flyoutHolder.children().eq(pos).before(button);
+ } else {
+ flyoutHolder.append(button);
+ curH.reverse();
+ }
+ }
+
+ if (!svgicons) {
+ button.append(icon);
+ }
+
+ if (!btn.list) {
+ // Add given events to button
+ $.each(btn.events, function (name, func) {
+ if (name === 'click' && btn.type === 'mode') {
+ if (btn.includeWith) {
button.bind(name, func);
+ } else {
+ button.bind(name, function () {
+ if (toolButtonClick(button)) {
+ func();
+ }
+ });
}
- });
- }
-
- setupFlyouts(holders);
- });
-
- $.each(btnSelects, function () {
- addAltDropDown(this.elem, this.list, this.callback, {seticon: true});
- });
-
- if (svgicons) {
- cbReady = false; // Delay callback
- }
-
- $.svgIcons(svgicons, {
- w: 24, h: 24,
- id_match: false,
- no_img: (!svgedit.browser.isWebkit()),
- fallback: fallbackObj,
- placement: placementObj,
- callback: function (icons) {
- // Non-ideal hack to make the icon match the current size
- // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
- if ($.pref('iconsize') !== 'm') {
- prepResize();
+ if (btn.key) {
+ $(document).bind('keydown', btn.key, func);
+ if (btn.title) {
+ button.attr('title', btn.title + ' [' + btn.key + ']');
+ }
+ }
+ } else {
+ button.bind(name, func);
}
- cbReady = true; // Ready for callback
- runCallback();
- }
- });
- }
-
- runCallback();
- };
-
- var getPaint = function (color, opac, type) {
- // update the editor's fill paint
- var opts = { alpha: opac };
- if (color.indexOf('url(#') === 0) {
- var refElem = svgCanvas.getRefElem(color);
- if (refElem) {
- refElem = refElem.cloneNode(true);
- } else {
- refElem = $('#' + type + '_color defs *')[0];
+ });
}
- opts[refElem.tagName] = refElem;
- } else if (color.indexOf('#') === 0) {
- opts.solidColor = color.substr(1);
- } else {
- opts.solidColor = 'none';
- }
- return new $.jGraduate.Paint(opts);
- };
- // $('#text').focus(function () { textBeingEntered = true; });
- // $('#text').blur(function () { textBeingEntered = false; });
-
- // bind the selected event to our function that handles updates to the UI
- svgCanvas.bind('selected', selectedChanged);
- svgCanvas.bind('transition', elementTransition);
- svgCanvas.bind('changed', elementChanged);
- svgCanvas.bind('saved', saveHandler);
- svgCanvas.bind('exported', exportHandler);
- svgCanvas.bind('exportedPDF', function (win, data) {
- var exportWindowName = data.exportWindowName;
- if (exportWindowName) {
- exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one
- }
- exportWindow.location.href = data.dataurlstring;
- });
- svgCanvas.bind('zoomed', zoomChanged);
- svgCanvas.bind('contextset', contextChanged);
- svgCanvas.bind('extension_added', extAdded);
- svgCanvas.textActions.setInputElem($('#text')[0]);
-
- var str = '
';
- $.each(palette, function (i, item) {
- str += '
';
- });
- $('#palette').append(str);
-
- // Set up editor background functionality
- // TODO add checkerboard as "pattern"
- var colorBlocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)'];
- str = '';
- $.each(colorBlocks, function () {
- str += '
';
- });
- $('#bg_blocks').append(str);
- var blocks = $('#bg_blocks div');
- var curBg = 'cur_background';
- blocks.each(function () {
- var blk = $(this);
- blk.click(function () {
- blocks.removeClass(curBg);
- $(this).addClass(curBg);
+ setupFlyouts(holders);
});
- });
- setBackground($.pref('bkgd_color'), $.pref('bkgd_url'));
+ $.each(btnSelects, function () {
+ addAltDropDown(this.elem, this.list, this.callback, {seticon: true});
+ });
- $('#image_save_opts input').val([$.pref('img_save')]);
-
- var changeRectRadius = function (ctl) {
- svgCanvas.setRectRadius(ctl.value);
- };
-
- var changeFontSize = function (ctl) {
- svgCanvas.setFontSize(ctl.value);
- };
-
- var changeStrokeWidth = function (ctl) {
- var val = ctl.value;
- if (val === 0 && selectedElement && ['line', 'polyline'].indexOf(selectedElement.nodeName) >= 0) {
- val = ctl.value = 1;
- }
- svgCanvas.setStrokeWidth(val);
- };
-
- var changeRotationAngle = function (ctl) {
- svgCanvas.setRotationAngle(ctl.value);
- $('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0);
- };
-
- var changeOpacity = function (ctl, val) {
- if (val == null) { val = ctl.value; }
- $('#group_opacity').val(val);
- if (!ctl || !ctl.handle) {
- $('#opac_slider').slider('option', 'value', val);
- }
- svgCanvas.setOpacity(val / 100);
- };
-
- var changeBlur = function (ctl, val, noUndo) {
- if (val == null) { val = ctl.value; }
- $('#blur').val(val);
- var complete = false;
- if (!ctl || !ctl.handle) {
- $('#blur_slider').slider('option', 'value', val);
- complete = true;
- }
- if (noUndo) {
- svgCanvas.setBlurNoUndo(val);
- } else {
- svgCanvas.setBlur(val, complete);
- }
- };
-
- $('#stroke_style').change(function () {
- svgCanvas.setStrokeAttr('stroke-dasharray', $(this).val());
- operaRepaint();
- });
-
- $('#stroke_linejoin').change(function () {
- svgCanvas.setStrokeAttr('stroke-linejoin', $(this).val());
- operaRepaint();
- });
-
- // Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
- $('select').change(function () { $(this).blur(); });
-
- // fired when user wants to move elements to another layer
- var promptMoveLayerOnce = false;
- $('#selLayerNames').change(function () {
- var destLayer = this.options[this.selectedIndex].value;
- var confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer);
- var moveToLayer = function (ok) {
- if (!ok) { return; }
- promptMoveLayerOnce = true;
- svgCanvas.moveSelectedToLayer(destLayer);
- svgCanvas.clearSelection();
- populateLayers();
- };
- if (destLayer) {
- if (promptMoveLayerOnce) {
- moveToLayer(true);
- } else {
- $.confirm(confirmStr, moveToLayer);
- }
- }
- });
-
- $('#font_family').change(function () {
- svgCanvas.setFontFamily(this.value);
- });
-
- $('#seg_type').change(function () {
- svgCanvas.setSegType($(this).val());
- });
-
- $('#text').bind('keyup input', function () {
- svgCanvas.setTextContent(this.value);
- });
-
- $('#image_url').change(function () {
- setImageURL(this.value);
- });
-
- $('#link_url').change(function () {
- if (this.value.length) {
- svgCanvas.setLinkURL(this.value);
- } else {
- svgCanvas.removeHyperlink();
- }
- });
-
- $('#g_title').change(function () {
- svgCanvas.setGroupTitle(this.value);
- });
-
- $('.attr_changer').change(function () {
- var attr = this.getAttribute('data-attr');
- var val = this.value;
- var valid = svgedit.units.isValidUnit(attr, val, selectedElement);
-
- if (!valid) {
- $.alert(uiStrings.notification.invalidAttrValGiven);
- this.value = selectedElement.getAttribute(attr);
- return false;
+ if (svgicons) {
+ cbReady = false; // Delay callback
}
- if (attr !== 'id' && attr !== 'class') {
- if (isNaN(val)) {
- val = svgCanvas.convertToNum(attr, val);
- } else if (curConfig.baseUnit !== 'px') {
- // Convert unitless value to one with given unit
-
- var unitData = svgedit.units.getTypeMap();
-
- if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') {
- val *= unitData[curConfig.baseUnit];
+ $.svgIcons(svgicons, {
+ w: 24, h: 24,
+ id_match: false,
+ no_img: (!isWebkit()),
+ fallback: fallbackObj,
+ placement: placementObj,
+ callback (icons) {
+ // Non-ideal hack to make the icon match the current size
+ // if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
+ if ($.pref('iconsize') !== 'm') {
+ prepResize();
}
+ cbReady = true; // Ready for callback
+ runCallback();
+ }
+ });
+ }
+
+ runCallback();
+ };
+
+ const getPaint = function (color, opac, type) {
+ // update the editor's fill paint
+ const opts = { alpha: opac };
+ if (color.startsWith('url(#')) {
+ let refElem = svgCanvas.getRefElem(color);
+ if (refElem) {
+ refElem = refElem.cloneNode(true);
+ } else {
+ refElem = $('#' + type + '_color defs *')[0];
+ }
+ opts[refElem.tagName] = refElem;
+ } else if (color.startsWith('#')) {
+ opts.solidColor = color.substr(1);
+ } else {
+ opts.solidColor = 'none';
+ }
+ return new $.jGraduate.Paint(opts);
+ };
+
+ // $('#text').focus(function () { textBeingEntered = true; });
+ // $('#text').blur(function () { textBeingEntered = false; });
+
+ // bind the selected event to our function that handles updates to the UI
+ svgCanvas.bind('selected', selectedChanged);
+ svgCanvas.bind('transition', elementTransition);
+ svgCanvas.bind('changed', elementChanged);
+ svgCanvas.bind('saved', saveHandler);
+ svgCanvas.bind('exported', exportHandler);
+ svgCanvas.bind('exportedPDF', function (win, data) {
+ const {exportWindowName} = data;
+ if (exportWindowName) {
+ exportWindow = window.open('', exportWindowName); // A hack to get the window via JSON-able name without opening a new one
+ }
+ exportWindow.location.href = data.dataurlstring;
+ });
+ svgCanvas.bind('zoomed', zoomChanged);
+ svgCanvas.bind('contextset', contextChanged);
+ svgCanvas.bind('extension_added', extAdded);
+ svgCanvas.textActions.setInputElem($('#text')[0]);
+
+ let str = '
';
+ $.each(palette, function (i, item) {
+ str += '
';
+ });
+ $('#palette').append(str);
+
+ // Set up editor background functionality
+ // TODO add checkerboard as "pattern"
+ const colorBlocks = ['#FFF', '#888', '#000']; // ,'url(data:image/gif;base64,R0lGODlhEAAQAIAAAP%2F%2F%2F9bW1iH5BAAAAAAALAAAAAAQABAAAAIfjG%2Bgq4jM3IFLJgpswNly%2FXkcBpIiVaInlLJr9FZWAQA7)'];
+ str = '';
+ $.each(colorBlocks, function () {
+ str += '
';
+ });
+ $('#bg_blocks').append(str);
+ const blocks = $('#bg_blocks div');
+ const curBg = 'cur_background';
+ blocks.each(function () {
+ const blk = $(this);
+ blk.click(function () {
+ blocks.removeClass(curBg);
+ $(this).addClass(curBg);
+ });
+ });
+
+ setBackground($.pref('bkgd_color'), $.pref('bkgd_url'));
+
+ $('#image_save_opts input').val([$.pref('img_save')]);
+
+ const changeRectRadius = function (ctl) {
+ svgCanvas.setRectRadius(ctl.value);
+ };
+
+ const changeFontSize = function (ctl) {
+ svgCanvas.setFontSize(ctl.value);
+ };
+
+ const changeStrokeWidth = function (ctl) {
+ let val = ctl.value;
+ if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) {
+ val = ctl.value = 1;
+ }
+ svgCanvas.setStrokeWidth(val);
+ };
+
+ const changeRotationAngle = function (ctl) {
+ svgCanvas.setRotationAngle(ctl.value);
+ $('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0);
+ };
+
+ const changeOpacity = function (ctl, val) {
+ if (val == null) { val = ctl.value; }
+ $('#group_opacity').val(val);
+ if (!ctl || !ctl.handle) {
+ $('#opac_slider').slider('option', 'value', val);
+ }
+ svgCanvas.setOpacity(val / 100);
+ };
+
+ const changeBlur = function (ctl, val, noUndo) {
+ if (val == null) { val = ctl.value; }
+ $('#blur').val(val);
+ let complete = false;
+ if (!ctl || !ctl.handle) {
+ $('#blur_slider').slider('option', 'value', val);
+ complete = true;
+ }
+ if (noUndo) {
+ svgCanvas.setBlurNoUndo(val);
+ } else {
+ svgCanvas.setBlur(val, complete);
+ }
+ };
+
+ $('#stroke_style').change(function () {
+ svgCanvas.setStrokeAttr('stroke-dasharray', $(this).val());
+ operaRepaint();
+ });
+
+ $('#stroke_linejoin').change(function () {
+ svgCanvas.setStrokeAttr('stroke-linejoin', $(this).val());
+ operaRepaint();
+ });
+
+ // Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
+ $('select').change(function () { $(this).blur(); });
+
+ // fired when user wants to move elements to another layer
+ let promptMoveLayerOnce = false;
+ $('#selLayerNames').change(function () {
+ const destLayer = this.options[this.selectedIndex].value;
+ const confirmStr = uiStrings.notification.QmoveElemsToLayer.replace('%s', destLayer);
+ const moveToLayer = function (ok) {
+ if (!ok) { return; }
+ promptMoveLayerOnce = true;
+ svgCanvas.moveSelectedToLayer(destLayer);
+ svgCanvas.clearSelection();
+ populateLayers();
+ };
+ if (destLayer) {
+ if (promptMoveLayerOnce) {
+ moveToLayer(true);
+ } else {
+ $.confirm(confirmStr, moveToLayer);
+ }
+ }
+ });
+
+ $('#font_family').change(function () {
+ svgCanvas.setFontFamily(this.value);
+ });
+
+ $('#seg_type').change(function () {
+ svgCanvas.setSegType($(this).val());
+ });
+
+ $('#text').bind('keyup input', function () {
+ svgCanvas.setTextContent(this.value);
+ });
+
+ $('#image_url').change(function () {
+ setImageURL(this.value);
+ });
+
+ $('#link_url').change(function () {
+ if (this.value.length) {
+ svgCanvas.setLinkURL(this.value);
+ } else {
+ svgCanvas.removeHyperlink();
+ }
+ });
+
+ $('#g_title').change(function () {
+ svgCanvas.setGroupTitle(this.value);
+ });
+
+ $('.attr_changer').change(function () {
+ const attr = this.getAttribute('data-attr');
+ let val = this.value;
+ const valid = isValidUnit(attr, val, selectedElement);
+
+ if (!valid) {
+ $.alert(uiStrings.notification.invalidAttrValGiven);
+ this.value = selectedElement.getAttribute(attr);
+ return false;
+ }
+
+ if (attr !== 'id' && attr !== 'class') {
+ if (isNaN(val)) {
+ val = svgCanvas.convertToNum(attr, val);
+ } else if (curConfig.baseUnit !== 'px') {
+ // Convert unitless value to one with given unit
+
+ const unitData = getTypeMap();
+
+ if (selectedElement[attr] || svgCanvas.getMode() === 'pathedit' || attr === 'x' || attr === 'y') {
+ val *= unitData[curConfig.baseUnit];
}
}
+ }
- // if the user is changing the id, then de-select the element first
- // change the ID, then re-select it with the new ID
- if (attr === 'id') {
- var elem = selectedElement;
- svgCanvas.clearSelection();
- elem.id = val;
- svgCanvas.addToSelection([elem], true);
- } else {
- svgCanvas.changeSelectedAttribute(attr, val);
- }
- this.blur();
- });
+ // if the user is changing the id, then de-select the element first
+ // change the ID, then re-select it with the new ID
+ if (attr === 'id') {
+ const elem = selectedElement;
+ svgCanvas.clearSelection();
+ elem.id = val;
+ svgCanvas.addToSelection([elem], true);
+ } else {
+ svgCanvas.changeSelectedAttribute(attr, val);
+ }
+ this.blur();
+ });
- // Prevent selection of elements when shift-clicking
- $('#palette').mouseover(function () {
- var inp = $('
');
- $(this).append(inp);
- inp.focus().remove();
- });
+ // Prevent selection of elements when shift-clicking
+ $('#palette').mouseover(function () {
+ const inp = $('
');
+ $(this).append(inp);
+ inp.focus().remove();
+ });
- $('.palette_item').mousedown(function (evt) {
- // shift key or right click for stroke
- var picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';
- var color = $(this).data('rgb');
- var paint;
+ $('.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)});
- }
+ // 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);
+ 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(); });
+ if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) {
+ svgCanvas.setPaintOpacity(picker, 1.0);
+ }
+ updateToolButtonState();
+ }).bind('contextmenu', function (e) { e.preventDefault(); });
- $('#toggle_stroke_tools').on('click', function () {
- $('#tools_bottom').toggleClass('expanded');
- });
+ $('#toggle_stroke_tools').on('click', function () {
+ $('#tools_bottom').toggleClass('expanded');
+ });
- (function () {
- var lastX = null, lastY = null, wArea = workarea[0],
- panning = false, keypan = false;
+ (function () {
+ const wArea = workarea[0];
- $('#svgcanvas').bind('mousemove mouseup', function (evt) {
- if (panning === false) { return; }
+ let lastX = null, lastY = null,
+ panning = false, keypan = false;
- wArea.scrollLeft -= (evt.clientX - lastX);
- wArea.scrollTop -= (evt.clientY - lastY);
+ $('#svgcanvas').bind('mousemove mouseup', function (evt) {
+ if (panning === false) { return; }
+ wArea.scrollLeft -= (evt.clientX - lastX);
+ wArea.scrollTop -= (evt.clientY - lastY);
+
+ lastX = evt.clientX;
+ lastY = evt.clientY;
+
+ if (evt.type === 'mouseup') { panning = false; }
+ return false;
+ }).mousedown(function (evt) {
+ if (evt.button === 1 || keypan === true) {
+ panning = true;
lastX = evt.clientX;
lastY = evt.clientY;
-
- if (evt.type === 'mouseup') { panning = false; }
return false;
- }).mousedown(function (evt) {
- if (evt.button === 1 || keypan === true) {
- panning = true;
- lastX = evt.clientX;
- lastY = evt.clientY;
- return false;
- }
- });
-
- $(window).mouseup(function () {
- panning = false;
- });
-
- $(document).bind('keydown', 'space', function (evt) {
- svgCanvas.spaceKey = keypan = true;
- evt.preventDefault();
- }).bind('keyup', 'space', function (evt) {
- evt.preventDefault();
- svgCanvas.spaceKey = keypan = false;
- }).bind('keydown', 'shift', function (evt) {
- if (svgCanvas.getMode() === 'zoom') {
- workarea.css('cursor', zoomOutIcon);
- }
- }).bind('keyup', 'shift', function (evt) {
- if (svgCanvas.getMode() === 'zoom') {
- workarea.css('cursor', zoomInIcon);
- }
- });
-
- editor.setPanning = function (active) {
- svgCanvas.spaceKey = keypan = active;
- };
- }());
-
- (function () {
- var button = $('#main_icon');
- var overlay = $('#main_icon span');
- var list = $('#main_menu');
- var onButton = false;
- var height = 0;
- var jsHover = true;
- var setClick = false;
-
- /*
- // Currently unused
- var hideMenu = function () {
- list.fadeOut(200);
- };
- */
-
- $(window).mouseup(function (evt) {
- if (!onButton) {
- button.removeClass('buttondown');
- // do not hide if it was the file input as that input needs to be visible
- // for its change event to fire
- if (evt.target.tagName !== 'INPUT') {
- list.fadeOut(200);
- } else if (!setClick) {
- setClick = true;
- $(evt.target).click(function () {
- list.css('margin-left', '-9999px').show();
- });
- }
- }
- onButton = false;
- }).mousedown(function (evt) {
- // $('.contextMenu').hide();
- var islib = $(evt.target).closest('div.tools_flyout, .contextMenu').length;
- if (!islib) {
- $('.tools_flyout:visible,.contextMenu').fadeOut(250);
- }
- });
-
- overlay.bind('mousedown', function () {
- if (!button.hasClass('buttondown')) {
- // Margin must be reset in case it was changed before;
- list.css('margin-left', 0).show();
- if (!height) {
- height = list.height();
- }
- // Using custom animation as slideDown has annoying 'bounce effect'
- list.css('height', 0).animate({
- 'height': height
- }, 200);
- onButton = true;
- } else {
- list.fadeOut(200);
- }
- button.toggleClass('buttondown buttonup');
- }).hover(function () {
- onButton = true;
- }).mouseout(function () {
- onButton = false;
- });
-
- var listItems = $('#main_menu li');
-
- // Check if JS method of hovering needs to be used (Webkit bug)
- listItems.mouseover(function () {
- jsHover = ($(this).css('background-color') === 'rgba(0, 0, 0, 0)');
-
- listItems.unbind('mouseover');
- if (jsHover) {
- listItems.mouseover(function () {
- this.style.backgroundColor = '#FFC';
- }).mouseout(function () {
- this.style.backgroundColor = 'transparent';
- return true;
- });
- }
- });
- }());
- // Made public for UI customization.
- // TODO: Group UI functions into a public editor.ui interface.
- editor.addDropDown = function (elem, callback, dropUp) {
- if ($(elem).length === 0) { return; } // Quit if called on non-existant element
- var button = $(elem).find('button');
- var list = $(elem).find('ul').attr('id', $(elem)[0].id + '-list');
- var onButton = false;
- if (dropUp) {
- $(elem).addClass('dropup');
- } else {
- // Move list to place where it can overflow container
- $('#option_lists').append(list);
- }
- list.find('li').bind('mouseup', callback);
-
- $(window).mouseup(function (evt) {
- if (!onButton) {
- button.removeClass('down');
- list.hide();
- }
- onButton = false;
- });
-
- button.bind('mousedown', function () {
- if (!button.hasClass('down')) {
- if (!dropUp) {
- var pos = $(elem).position();
- list.css({
- top: pos.top + 24,
- left: pos.left - 10
- });
- }
- list.show();
- onButton = true;
- } else {
- list.hide();
- }
- button.toggleClass('down');
- }).hover(function () {
- onButton = true;
- }).mouseout(function () {
- onButton = false;
- });
- };
-
- editor.addDropDown('#font_family_dropdown', function () {
- $('#font_family').val($(this).text()).change();
- });
-
- editor.addDropDown('#opacity_dropdown', function () {
- if ($(this).find('div').length) { return; }
- var perc = parseInt($(this).text().split('%')[0], 10);
- changeOpacity(false, perc);
- }, true);
-
- // For slider usage, see: https://jqueryui.com/demos/slider/
- $('#opac_slider').slider({
- start: function () {
- $('#opacity_dropdown li:not(.special)').hide();
- },
- stop: function () {
- $('#opacity_dropdown li').show();
- $(window).mouseup();
- },
- slide: function (evt, ui) {
- changeOpacity(ui);
}
});
- editor.addDropDown('#blur_dropdown', $.noop);
-
- var slideStart = false;
-
- $('#blur_slider').slider({
- max: 10,
- step: 0.1,
- stop: function (evt, ui) {
- slideStart = false;
- changeBlur(ui);
- $('#blur_dropdown li').show();
- $(window).mouseup();
- },
- start: function () {
- slideStart = true;
- },
- slide: function (evt, ui) {
- changeBlur(ui, null, slideStart);
- }
+ $(window).mouseup(function () {
+ panning = false;
});
- editor.addDropDown('#zoom_dropdown', function () {
- var item = $(this);
- var val = item.data('val');
- if (val) {
- zoomChanged(window, val);
- } else {
- changeZoom({value: parseFloat(item.text())});
+ $(document).bind('keydown', 'space', function (evt) {
+ svgCanvas.spaceKey = keypan = true;
+ evt.preventDefault();
+ }).bind('keyup', 'space', function (evt) {
+ evt.preventDefault();
+ svgCanvas.spaceKey = keypan = false;
+ }).bind('keydown', 'shift', function (evt) {
+ if (svgCanvas.getMode() === 'zoom') {
+ workarea.css('cursor', zoomOutIcon);
}
- }, true);
-
- addAltDropDown('#stroke_linecap', '#linecap_opts', function () {
- setStrokeOpt(this, true);
- }, {dropUp: true});
-
- addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () {
- setStrokeOpt(this, true);
- }, {dropUp: true});
-
- addAltDropDown('#tool_position', '#position_opts', function () {
- var letter = this.id.replace('tool_pos', '').charAt(0);
- svgCanvas.alignSelectedElements(letter, 'page');
- }, {multiclick: true});
-
- /*
-
- When a flyout icon is selected
- (if flyout) {
- - Change the icon
- - Make pressing the button run its stuff
- }
- - Run its stuff
-
- When its shortcut key is pressed
- - If not current in list, do as above
- , else:
- - Just run its stuff
-
- */
-
- // Unfocus text input when workarea is mousedowned.
- (function () {
- var inp;
- var unfocus = function () {
- $(inp).blur();
- };
-
- $('#svg_editor').find('button, select, input:not(#text)').focus(function () {
- inp = this;
- uiContext = 'toolbars';
- workarea.mousedown(unfocus);
- }).blur(function () {
- uiContext = 'canvas';
- workarea.unbind('mousedown', unfocus);
- // Go back to selecting text if in textedit mode
- if (svgCanvas.getMode() === 'textedit') {
- $('#text').focus();
- }
- });
- }());
-
- var clickFHPath = function () {
- if (toolButtonClick('#tool_fhpath')) {
- svgCanvas.setMode('fhpath');
- }
- };
-
- var clickLine = function () {
- if (toolButtonClick('#tool_line')) {
- svgCanvas.setMode('line');
- }
- };
-
- var clickSquare = function () {
- if (toolButtonClick('#tool_square')) {
- svgCanvas.setMode('square');
- }
- };
-
- var clickRect = function () {
- if (toolButtonClick('#tool_rect')) {
- svgCanvas.setMode('rect');
- }
- };
-
- var clickFHRect = function () {
- if (toolButtonClick('#tool_fhrect')) {
- svgCanvas.setMode('fhrect');
- }
- };
-
- var clickCircle = function () {
- if (toolButtonClick('#tool_circle')) {
- svgCanvas.setMode('circle');
- }
- };
-
- var clickEllipse = function () {
- if (toolButtonClick('#tool_ellipse')) {
- svgCanvas.setMode('ellipse');
- }
- };
-
- var clickFHEllipse = function () {
- if (toolButtonClick('#tool_fhellipse')) {
- svgCanvas.setMode('fhellipse');
- }
- };
-
- var clickImage = function () {
- if (toolButtonClick('#tool_image')) {
- svgCanvas.setMode('image');
- }
- };
-
- var clickZoom = function () {
- if (toolButtonClick('#tool_zoom')) {
- svgCanvas.setMode('zoom');
+ }).bind('keyup', 'shift', function (evt) {
+ if (svgCanvas.getMode() === 'zoom') {
workarea.css('cursor', zoomInIcon);
}
- };
+ });
- var zoomImage = function (multiplier) {
- var res = svgCanvas.getResolution();
- multiplier = multiplier ? res.zoom * multiplier : 1;
- // setResolution(res.w * multiplier, res.h * multiplier, true);
- $('#zoom').val(multiplier * 100);
- svgCanvas.setZoom(multiplier);
- zoomDone();
- updateCanvas(true);
+ editor.setPanning = function (active) {
+ svgCanvas.spaceKey = keypan = active;
};
+ }());
- var dblclickZoom = function () {
- if (toolButtonClick('#tool_zoom')) {
- zoomImage();
- setSelectMode();
+ (function () {
+ const button = $('#main_icon');
+ const overlay = $('#main_icon span');
+ const list = $('#main_menu');
+
+ let onButton = false;
+ let height = 0;
+ let jsHover = true;
+ let setClick = false;
+
+ /*
+ // Currently unused
+ const hideMenu = function () {
+ list.fadeOut(200);
+ };
+ */
+
+ $(window).mouseup(function (evt) {
+ if (!onButton) {
+ button.removeClass('buttondown');
+ // do not hide if it was the file input as that input needs to be visible
+ // for its change event to fire
+ if (evt.target.tagName !== 'INPUT') {
+ list.fadeOut(200);
+ } else if (!setClick) {
+ setClick = true;
+ $(evt.target).click(function () {
+ list.css('margin-left', '-9999px').show();
+ });
+ }
}
- };
-
- var clickText = function () {
- if (toolButtonClick('#tool_text')) {
- svgCanvas.setMode('text');
+ onButton = false;
+ }).mousedown(function (evt) {
+ // $('.contextMenu').hide();
+ const islib = $(evt.target).closest('div.tools_flyout, .contextMenu').length;
+ if (!islib) {
+ $('.tools_flyout:visible,.contextMenu').fadeOut(250);
}
- };
+ });
- var clickPath = function () {
- if (toolButtonClick('#tool_path')) {
- svgCanvas.setMode('path');
+ overlay.bind('mousedown', function () {
+ if (!button.hasClass('buttondown')) {
+ // Margin must be reset in case it was changed before;
+ list.css('margin-left', 0).show();
+ if (!height) {
+ height = list.height();
+ }
+ // Using custom animation as slideDown has annoying 'bounce effect'
+ list.css('height', 0).animate({
+ height
+ }, 200);
+ onButton = true;
+ } else {
+ list.fadeOut(200);
}
- };
+ button.toggleClass('buttondown buttonup');
+ }).hover(function () {
+ onButton = true;
+ }).mouseout(function () {
+ onButton = false;
+ });
- // Delete is a contextual tool that only appears in the ribbon if
- // an element has been selected
- var deleteSelected = function () {
- if (selectedElement != null || multiselected) {
- svgCanvas.deleteSelectedElements();
- }
- };
+ const listItems = $('#main_menu li');
- var cutSelected = function () {
- if (selectedElement != null || multiselected) {
- svgCanvas.cutSelectedElements();
- }
- };
+ // Check if JS method of hovering needs to be used (Webkit bug)
+ listItems.mouseover(function () {
+ jsHover = ($(this).css('background-color') === 'rgba(0, 0, 0, 0)');
- var copySelected = function () {
- if (selectedElement != null || multiselected) {
- svgCanvas.copySelectedElements();
- }
- };
-
- var pasteInCenter = function () {
- var zoom = svgCanvas.getZoom();
- var x = (workarea[0].scrollLeft + workarea.width() / 2) / zoom - svgCanvas.contentW;
- var y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH;
- svgCanvas.pasteElements('point', x, y);
- };
-
- var moveToTopSelected = function () {
- if (selectedElement != null) {
- svgCanvas.moveToTopSelectedElement();
- }
- };
-
- var moveToBottomSelected = function () {
- if (selectedElement != null) {
- svgCanvas.moveToBottomSelectedElement();
- }
- };
-
- var moveUpDownSelected = function (dir) {
- if (selectedElement != null) {
- svgCanvas.moveUpDownSelected(dir);
- }
- };
-
- var convertToPath = function () {
- if (selectedElement != null) {
- svgCanvas.convertToPath();
- }
- };
-
- var reorientPath = function () {
- if (selectedElement != null) {
- path.reorient();
- }
- };
-
- var makeHyperlink = function () {
- if (selectedElement != null || multiselected) {
- $.prompt(uiStrings.notification.enterNewLinkURL, 'https://', function (url) {
- if (url) { svgCanvas.makeHyperlink(url); }
+ listItems.unbind('mouseover');
+ if (jsHover) {
+ listItems.mouseover(function () {
+ this.style.backgroundColor = '#FFC';
+ }).mouseout(function () {
+ this.style.backgroundColor = 'transparent';
+ return true;
});
}
- };
+ });
+ }());
+ // Made public for UI customization.
+ // TODO: Group UI functions into a public editor.ui interface.
+ editor.addDropDown = function (elem, callback, dropUp) {
+ if (!$(elem).length) { return; } // Quit if called on non-existant element
+ const button = $(elem).find('button');
+ const list = $(elem).find('ul').attr('id', $(elem)[0].id + '-list');
+ if (dropUp) {
+ $(elem).addClass('dropup');
+ } else {
+ // Move list to place where it can overflow container
+ $('#option_lists').append(list);
+ }
+ list.find('li').bind('mouseup', callback);
- var moveSelected = function (dx, dy) {
- if (selectedElement != null || multiselected) {
- if (curConfig.gridSnapping) {
- // Use grid snap value regardless of zoom level
- var multi = svgCanvas.getZoom() * curConfig.snappingStep;
- dx *= multi;
- dy *= multi;
+ let onButton = false;
+ $(window).mouseup(function (evt) {
+ if (!onButton) {
+ button.removeClass('down');
+ list.hide();
+ }
+ onButton = false;
+ });
+
+ button.bind('mousedown', function () {
+ if (!button.hasClass('down')) {
+ if (!dropUp) {
+ const pos = $(elem).position();
+ list.css({
+ top: pos.top + 24,
+ left: pos.left - 10
+ });
}
- svgCanvas.moveSelectedElements(dx, dy);
- }
- };
-
- var linkControlPoints = function () {
- $('#tool_node_link').toggleClass('push_button_pressed tool_button');
- var linked = $('#tool_node_link').hasClass('push_button_pressed');
- path.linkControlPoints(linked);
- };
-
- var clonePathNode = function () {
- if (path.getNodePoint()) {
- path.clonePathNode();
- }
- };
-
- var deletePathNode = function () {
- if (path.getNodePoint()) {
- path.deletePathNode();
- }
- };
-
- var addSubPath = function () {
- var button = $('#tool_add_subpath');
- var sp = !button.hasClass('push_button_pressed');
- button.toggleClass('push_button_pressed tool_button');
- path.addSubPath(sp);
- };
-
- var opencloseSubPath = function () {
- path.opencloseSubPath();
- };
-
- var selectNext = function () {
- svgCanvas.cycleElement(1);
- };
-
- var selectPrev = function () {
- svgCanvas.cycleElement(0);
- };
-
- var rotateSelected = function (cw, step) {
- if (selectedElement == null || multiselected) { return; }
- if (!cw) { step *= -1; }
- var angle = parseFloat($('#angle').val()) + step;
- svgCanvas.setRotationAngle(angle);
- updateContextPanel();
- };
-
- var clickClear = function () {
- var dims = curConfig.dimensions;
- $.confirm(uiStrings.notification.QwantToClear, function (ok) {
- if (!ok) { return; }
- setSelectMode();
- svgCanvas.clear();
- svgCanvas.setResolution(dims[0], dims[1]);
- updateCanvas(true);
- zoomImage();
- populateLayers();
- updateContextPanel();
- prepPaints();
- svgCanvas.runExtensions('onNewDocument');
- });
- };
-
- var clickBold = function () {
- svgCanvas.setBold(!svgCanvas.getBold());
- updateContextPanel();
- return false;
- };
-
- var clickItalic = function () {
- svgCanvas.setItalic(!svgCanvas.getItalic());
- updateContextPanel();
- return false;
- };
-
- var clickSave = function () {
- // In the future, more options can be provided here
- var saveOpts = {
- 'images': $.pref('img_save'),
- 'round_digits': 6
- };
- svgCanvas.save(saveOpts);
- };
-
- var loadingURL;
- var clickExport = function () {
- $.select('Select an image type for export: ', [
- // See https://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support
- // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG'
- 'PNG',
- 'JPEG', 'BMP', 'WEBP', 'PDF'
- ], function (imgType) { // todo: replace hard-coded msg with uiStrings.notification.
- if (!imgType) {
- return;
- }
- // Open placeholder window (prevents popup)
- var exportWindowName;
- function openExportWindow () {
- var str = uiStrings.notification.loadingImage;
- if (curConfig.exportWindowType === 'new') {
- editor.exportWindowCt++;
- }
- exportWindowName = curConfig.canvasName + editor.exportWindowCt;
- var popHTML, popURL;
- if (loadingURL) {
- popURL = loadingURL;
- } else {
- popHTML = '
' + str + '' + str + '
';
- if (typeof URL && URL.createObjectURL) {
- var blob = new Blob([popHTML], {type: 'text/html'});
- popURL = URL.createObjectURL(blob);
- } else {
- popURL = 'data:text/html;base64;charset=utf-8,' + svgedit.utilities.encode64(popHTML);
- }
- loadingURL = popURL;
- }
- exportWindow = window.open(popURL, exportWindowName);
- }
- if (imgType === 'PDF') {
- if (!customExportPDF) {
- openExportWindow();
- }
- svgCanvas.exportPDF(exportWindowName);
- } else {
- if (!customExportImage) {
- openExportWindow();
- }
- var quality = parseInt($('#image-slider').val(), 10) / 100;
- svgCanvas.rasterExport(imgType, quality, exportWindowName);
- }
- }, function () {
- var sel = $(this);
- if (sel.val() === 'JPEG' || sel.val() === 'WEBP') {
- if (!$('#image-slider').length) {
- $('
').appendTo(sel.parent()); // Todo: i18n-ize label
- }
- } else {
- $('#image-slider').parent().remove();
- }
- });
- };
-
- // by default, svgCanvas.open() is a no-op.
- // it is up to an extension mechanism (opera widget, etc)
- // to call setCustomHandlers() which will make it do something
- var clickOpen = function () {
- svgCanvas.open();
- };
-
- var clickImport = function () {
- };
-
- var clickUndo = function () {
- if (undoMgr.getUndoStackSize() > 0) {
- undoMgr.undo();
- populateLayers();
- }
- };
-
- var clickRedo = function () {
- if (undoMgr.getRedoStackSize() > 0) {
- undoMgr.redo();
- populateLayers();
- }
- };
-
- var clickGroup = function () {
- // group
- if (multiselected) {
- svgCanvas.groupSelectedElements();
- // ungroup
- } else if (selectedElement) {
- svgCanvas.ungroupSelectedElement();
- }
- };
-
- var clickClone = function () {
- svgCanvas.cloneSelectedElements(20, 20);
- };
-
- var clickAlign = function () {
- var letter = this.id.replace('tool_align', '').charAt(0);
- svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val());
- };
-
- var clickWireframe = function () {
- $('#tool_wireframe').toggleClass('push_button_pressed tool_button');
- workarea.toggleClass('wireframe');
-
- if (supportsNonSS) { return; }
- var wfRules = $('#wireframe_rules');
- if (!wfRules.length) {
- wfRules = $('').appendTo('head');
+ list.show();
+ onButton = true;
} else {
- wfRules.empty();
+ list.hide();
}
+ button.toggleClass('down');
+ }).hover(function () {
+ onButton = true;
+ }).mouseout(function () {
+ onButton = false;
+ });
+ };
- updateWireFrame();
+ editor.addDropDown('#font_family_dropdown', function () {
+ $('#font_family').val($(this).text()).change();
+ });
+
+ editor.addDropDown('#opacity_dropdown', function () {
+ if ($(this).find('div').length) { return; }
+ const perc = parseInt($(this).text().split('%')[0], 10);
+ changeOpacity(false, perc);
+ }, true);
+
+ // For slider usage, see: http://jqueryui.com/demos/slider/
+ $('#opac_slider').slider({
+ start () {
+ $('#opacity_dropdown li:not(.special)').hide();
+ },
+ stop () {
+ $('#opacity_dropdown li').show();
+ $(window).mouseup();
+ },
+ slide (evt, ui) {
+ changeOpacity(ui);
+ }
+ });
+
+ editor.addDropDown('#blur_dropdown', $.noop);
+
+ let slideStart = false;
+ $('#blur_slider').slider({
+ max: 10,
+ step: 0.1,
+ stop (evt, ui) {
+ slideStart = false;
+ changeBlur(ui);
+ $('#blur_dropdown li').show();
+ $(window).mouseup();
+ },
+ start () {
+ slideStart = true;
+ },
+ slide (evt, ui) {
+ changeBlur(ui, null, slideStart);
+ }
+ });
+
+ editor.addDropDown('#zoom_dropdown', function () {
+ const item = $(this);
+ const val = item.data('val');
+ if (val) {
+ zoomChanged(window, val);
+ } else {
+ changeZoom({value: parseFloat(item.text())});
+ }
+ }, true);
+
+ addAltDropDown('#stroke_linecap', '#linecap_opts', function () {
+ setStrokeOpt(this, true);
+ }, {dropUp: true});
+
+ addAltDropDown('#stroke_linejoin', '#linejoin_opts', function () {
+ setStrokeOpt(this, true);
+ }, {dropUp: true});
+
+ addAltDropDown('#tool_position', '#position_opts', function () {
+ const letter = this.id.replace('tool_pos', '').charAt(0);
+ svgCanvas.alignSelectedElements(letter, 'page');
+ }, {multiclick: true});
+
+ /*
+
+ When a flyout icon is selected
+ (if flyout) {
+ - Change the icon
+ - Make pressing the button run its stuff
+ }
+ - Run its stuff
+
+ When its shortcut key is pressed
+ - If not current in list, do as above
+ , else:
+ - Just run its stuff
+
+ */
+
+ // Unfocus text input when workarea is mousedowned.
+ (function () {
+ let inp;
+ const unfocus = function () {
+ $(inp).blur();
};
- $('#svg_docprops_container, #svg_prefs_container').draggable({cancel: 'button,fieldset', containment: 'window'});
-
- var showDocProperties = function () {
- if (docprops) { return; }
- docprops = true;
-
- // This selects the correct radio button by using the array notation
- $('#image_save_opts input').val([$.pref('img_save')]);
-
- // update resolution option with actual resolution
- var res = svgCanvas.getResolution();
- if (curConfig.baseUnit !== 'px') {
- res.w = svgedit.units.convertUnit(res.w) + curConfig.baseUnit;
- res.h = svgedit.units.convertUnit(res.h) + curConfig.baseUnit;
+ $('#svg_editor').find('button, select, input:not(#text)').focus(function () {
+ inp = this;
+ uiContext = 'toolbars';
+ workarea.mousedown(unfocus);
+ }).blur(function () {
+ uiContext = 'canvas';
+ workarea.unbind('mousedown', unfocus);
+ // Go back to selecting text if in textedit mode
+ if (svgCanvas.getMode() === 'textedit') {
+ $('#text').focus();
}
+ });
+ }());
- $('#canvas_width').val(res.w);
- $('#canvas_height').val(res.h);
- $('#canvas_title').val(svgCanvas.getDocumentTitle());
+ const clickFHPath = function () {
+ if (toolButtonClick('#tool_fhpath')) {
+ svgCanvas.setMode('fhpath');
+ }
+ };
- $('#svg_docprops').show();
- };
+ const clickLine = function () {
+ if (toolButtonClick('#tool_line')) {
+ svgCanvas.setMode('line');
+ }
+ };
- var showPreferences = function () {
- if (preferences) { return; }
- preferences = true;
- $('#main_menu').hide();
+ const clickSquare = function () {
+ if (toolButtonClick('#tool_square')) {
+ svgCanvas.setMode('square');
+ }
+ };
- // Update background color with current one
- var blocks = $('#bg_blocks div');
- var curBg = 'cur_background';
- var canvasBg = curPrefs.bkgd_color;
- var url = $.pref('bkgd_url');
- blocks.each(function () {
- var blk = $(this);
- var isBg = blk.css('background-color') === canvasBg;
- blk.toggleClass(curBg, isBg);
- if (isBg) { $('#canvas_bg_url').removeClass(curBg); }
- });
- if (!canvasBg) { blocks.eq(0).addClass(curBg); }
- if (url) {
- $('#canvas_bg_url').val(url);
- }
- $('#grid_snapping_on').prop('checked', curConfig.gridSnapping);
- $('#grid_snapping_step').attr('value', curConfig.snappingStep);
- $('#grid_color').attr('value', curConfig.gridColor);
+ const clickRect = function () {
+ if (toolButtonClick('#tool_rect')) {
+ svgCanvas.setMode('rect');
+ }
+ };
- $('#svg_prefs').show();
- };
+ const clickFHRect = function () {
+ if (toolButtonClick('#tool_fhrect')) {
+ svgCanvas.setMode('fhrect');
+ }
+ };
- var hideSourceEditor = function () {
- $('#svg_source_editor').hide();
- editingsource = false;
- $('#svg_source_textarea').blur();
- };
+ const clickCircle = function () {
+ if (toolButtonClick('#tool_circle')) {
+ svgCanvas.setMode('circle');
+ }
+ };
- var saveSourceEditor = function () {
- if (!editingsource) { return; }
+ const clickEllipse = function () {
+ if (toolButtonClick('#tool_ellipse')) {
+ svgCanvas.setMode('ellipse');
+ }
+ };
- var saveChanges = function () {
- svgCanvas.clearSelection();
- hideSourceEditor();
- zoomImage();
- populateLayers();
- updateTitle();
- prepPaints();
- };
+ const clickFHEllipse = function () {
+ if (toolButtonClick('#tool_fhellipse')) {
+ svgCanvas.setMode('fhellipse');
+ }
+ };
- if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) {
- $.confirm(uiStrings.notification.QerrorsRevertToSource, function (ok) {
- if (!ok) { return false; }
- saveChanges();
- });
- } else {
- saveChanges();
- }
+ const clickImage = function () {
+ if (toolButtonClick('#tool_image')) {
+ svgCanvas.setMode('image');
+ }
+ };
+
+ const clickZoom = function () {
+ if (toolButtonClick('#tool_zoom')) {
+ svgCanvas.setMode('zoom');
+ workarea.css('cursor', zoomInIcon);
+ }
+ };
+
+ const zoomImage = function (multiplier) {
+ const res = svgCanvas.getResolution();
+ multiplier = multiplier ? res.zoom * multiplier : 1;
+ // setResolution(res.w * multiplier, res.h * multiplier, true);
+ $('#zoom').val(multiplier * 100);
+ svgCanvas.setZoom(multiplier);
+ zoomDone();
+ updateCanvas(true);
+ };
+
+ const dblclickZoom = function () {
+ if (toolButtonClick('#tool_zoom')) {
+ zoomImage();
setSelectMode();
- };
+ }
+ };
- var hideDocProperties = function () {
- $('#svg_docprops').hide();
- $('#canvas_width,#canvas_height').removeAttr('disabled');
- $('#resolution')[0].selectedIndex = 0;
- $('#image_save_opts input').val([$.pref('img_save')]);
- docprops = false;
- };
+ const clickText = function () {
+ if (toolButtonClick('#tool_text')) {
+ svgCanvas.setMode('text');
+ }
+ };
- var hidePreferences = function () {
- $('#svg_prefs').hide();
- preferences = false;
- };
+ const clickPath = function () {
+ if (toolButtonClick('#tool_path')) {
+ svgCanvas.setMode('path');
+ }
+ };
- var saveDocProperties = function () {
- // set title
- var newTitle = $('#canvas_title').val();
- updateTitle(newTitle);
- svgCanvas.setDocumentTitle(newTitle);
+ // Delete is a contextual tool that only appears in the ribbon if
+ // an element has been selected
+ const deleteSelected = function () {
+ if (selectedElement != null || multiselected) {
+ svgCanvas.deleteSelectedElements();
+ }
+ };
- // update resolution
- var width = $('#canvas_width'), w = width.val();
- var height = $('#canvas_height'), h = height.val();
+ const cutSelected = function () {
+ if (selectedElement != null || multiselected) {
+ svgCanvas.cutSelectedElements();
+ }
+ };
- if (w !== 'fit' && !svgedit.units.isValidUnit('width', w)) {
- $.alert(uiStrings.notification.invalidAttrValGiven);
- width.parent().addClass('error');
- return false;
+ const copySelected = function () {
+ if (selectedElement != null || multiselected) {
+ svgCanvas.copySelectedElements();
+ }
+ };
+
+ const pasteInCenter = function () {
+ const zoom = svgCanvas.getZoom();
+ const x = (workarea[0].scrollLeft + workarea.width() / 2) / zoom - svgCanvas.contentW;
+ const y = (workarea[0].scrollTop + workarea.height() / 2) / zoom - svgCanvas.contentH;
+ svgCanvas.pasteElements('point', x, y);
+ };
+
+ const moveToTopSelected = function () {
+ if (selectedElement != null) {
+ svgCanvas.moveToTopSelectedElement();
+ }
+ };
+
+ const moveToBottomSelected = function () {
+ if (selectedElement != null) {
+ svgCanvas.moveToBottomSelectedElement();
+ }
+ };
+
+ const moveUpDownSelected = function (dir) {
+ if (selectedElement != null) {
+ svgCanvas.moveUpDownSelected(dir);
+ }
+ };
+
+ const convertToPath = function () {
+ if (selectedElement != null) {
+ svgCanvas.convertToPath();
+ }
+ };
+
+ const reorientPath = function () {
+ if (selectedElement != null) {
+ path.reorient();
+ }
+ };
+
+ const makeHyperlink = function () {
+ if (selectedElement != null || multiselected) {
+ $.prompt(uiStrings.notification.enterNewLinkURL, 'http://', function (url) {
+ if (url) { svgCanvas.makeHyperlink(url); }
+ });
+ }
+ };
+
+ const moveSelected = function (dx, dy) {
+ if (selectedElement != null || multiselected) {
+ if (curConfig.gridSnapping) {
+ // Use grid snap value regardless of zoom level
+ const multi = svgCanvas.getZoom() * curConfig.snappingStep;
+ dx *= multi;
+ dy *= multi;
}
+ svgCanvas.moveSelectedElements(dx, dy);
+ }
+ };
- width.parent().removeClass('error');
+ const linkControlPoints = function () {
+ $('#tool_node_link').toggleClass('push_button_pressed tool_button');
+ const linked = $('#tool_node_link').hasClass('push_button_pressed');
+ path.linkControlPoints(linked);
+ };
- if (h !== 'fit' && !svgedit.units.isValidUnit('height', h)) {
- $.alert(uiStrings.notification.invalidAttrValGiven);
- height.parent().addClass('error');
- return false;
- }
+ const clonePathNode = function () {
+ if (path.getNodePoint()) {
+ path.clonePathNode();
+ }
+ };
- height.parent().removeClass('error');
+ const deletePathNode = function () {
+ if (path.getNodePoint()) {
+ path.deletePathNode();
+ }
+ };
- if (!svgCanvas.setResolution(w, h)) {
- $.alert(uiStrings.notification.noContentToFitTo);
- return false;
- }
+ const addSubPath = function () {
+ const button = $('#tool_add_subpath');
+ const sp = !button.hasClass('push_button_pressed');
+ button.toggleClass('push_button_pressed tool_button');
+ path.addSubPath(sp);
+ };
- // Set image save option
- $.pref('img_save', $('#image_save_opts :checked').val());
- updateCanvas();
- hideDocProperties();
+ const opencloseSubPath = function () {
+ path.opencloseSubPath();
+ };
+
+ const selectNext = function () {
+ svgCanvas.cycleElement(1);
+ };
+
+ const selectPrev = function () {
+ svgCanvas.cycleElement(0);
+ };
+
+ const rotateSelected = function (cw, step) {
+ if (selectedElement == null || multiselected) { return; }
+ if (!cw) { step *= -1; }
+ const angle = parseFloat($('#angle').val()) + step;
+ svgCanvas.setRotationAngle(angle);
+ updateContextPanel();
+ };
+
+ const clickClear = function () {
+ const dims = curConfig.dimensions;
+ $.confirm(uiStrings.notification.QwantToClear, function (ok) {
+ if (!ok) { return; }
+ setSelectMode();
+ svgCanvas.clear();
+ svgCanvas.setResolution(dims[0], dims[1]);
+ updateCanvas(true);
+ zoomImage();
+ populateLayers();
+ updateContextPanel();
+ prepPaints();
+ svgCanvas.runExtensions('onNewDocument');
+ });
+ };
+
+ const clickBold = function () {
+ svgCanvas.setBold(!svgCanvas.getBold());
+ updateContextPanel();
+ return false;
+ };
+
+ const clickItalic = function () {
+ svgCanvas.setItalic(!svgCanvas.getItalic());
+ updateContextPanel();
+ return false;
+ };
+
+ const clickSave = function () {
+ // In the future, more options can be provided here
+ const saveOpts = {
+ 'images': $.pref('img_save'),
+ 'round_digits': 6
};
+ svgCanvas.save(saveOpts);
+ };
- var savePreferences = editor.savePreferences = function () {
- // Set background
- var color = $('#bg_blocks div.cur_background').css('background-color') || '#FFF';
- setBackground(color, $('#canvas_bg_url').val());
-
- // set language
- var lang = $('#lang_select').val();
- if (lang !== $.pref('lang')) {
- editor.putLocale(lang, goodLangs);
- }
-
- // set icon size
- setIconSize($('#iconsize').val());
-
- // set grid setting
- curConfig.gridSnapping = $('#grid_snapping_on')[0].checked;
- curConfig.snappingStep = $('#grid_snapping_step').val();
- curConfig.gridColor = $('#grid_color').val();
- curConfig.showRulers = $('#show_rulers')[0].checked;
-
- $('#rulers').toggle(curConfig.showRulers);
- if (curConfig.showRulers) { updateRulers(); }
- curConfig.baseUnit = $('#base_unit').val();
-
- svgCanvas.setConfig(curConfig);
-
- updateCanvas();
- hidePreferences();
- };
-
- var resetScrollPos = $.noop;
-
- var cancelOverlays = function () {
- $('#dialog_box').hide();
- if (!editingsource && !docprops && !preferences) {
- if (curContext) {
- svgCanvas.leaveContext();
- }
+ let loadingURL;
+ const clickExport = function () {
+ $.select('Select an image type for export: ', [
+ // See http://kangax.github.io/jstests/toDataUrl_mime_type_test/ for a useful list of MIME types and browser support
+ // 'ICO', // Todo: Find a way to preserve transparency in SVG-Edit if not working presently and do full packaging for x-icon; then switch back to position after 'PNG'
+ 'PNG',
+ 'JPEG', 'BMP', 'WEBP', 'PDF'
+ ], function (imgType) { // todo: replace hard-coded msg with uiStrings.notification.
+ if (!imgType) {
return;
}
-
- if (editingsource) {
- if (origSource !== $('#svg_source_textarea').val()) {
- $.confirm(uiStrings.notification.QignoreSourceChanges, function (ok) {
- if (ok) { hideSourceEditor(); }
- });
- } else {
- hideSourceEditor();
+ // Open placeholder window (prevents popup)
+ let exportWindowName;
+ function openExportWindow () {
+ const str = uiStrings.notification.loadingImage;
+ if (curConfig.exportWindowType === 'new') {
+ editor.exportWindowCt++;
}
- } else if (docprops) {
- hideDocProperties();
- } else if (preferences) {
- hidePreferences();
+ exportWindowName = curConfig.canvasName + editor.exportWindowCt;
+ let popHTML, popURL;
+ if (loadingURL) {
+ popURL = loadingURL;
+ } else {
+ popHTML = '
' + str + '' + str + '
';
+ if (typeof URL && URL.createObjectURL) {
+ const blob = new Blob([popHTML], {type: 'text/html'});
+ popURL = URL.createObjectURL(blob);
+ } else {
+ popURL = 'data:text/html;base64;charset=utf-8,' + Utils.encode64(popHTML);
+ }
+ loadingURL = popURL;
+ }
+ exportWindow = window.open(popURL, exportWindowName);
}
- resetScrollPos();
+ if (imgType === 'PDF') {
+ if (!customExportPDF) {
+ openExportWindow();
+ }
+ svgCanvas.exportPDF(exportWindowName);
+ } else {
+ if (!customExportImage) {
+ openExportWindow();
+ }
+ const quality = parseInt($('#image-slider').val(), 10) / 100;
+ svgCanvas.rasterExport(imgType, quality, exportWindowName);
+ }
+ }, function () {
+ const sel = $(this);
+ if (sel.val() === 'JPEG' || sel.val() === 'WEBP') {
+ if (!$('#image-slider').length) {
+ $(`
`).appendTo(sel.parent());
+ }
+ } else {
+ $('#image-slider').parent().remove();
+ }
+ });
+ };
+
+ // by default, svgCanvas.open() is a no-op.
+ // it is up to an extension mechanism (opera widget, etc)
+ // to call setCustomHandlers() which will make it do something
+ const clickOpen = function () {
+ svgCanvas.open();
+ };
+
+ const clickImport = function () {
+ };
+
+ const clickUndo = function () {
+ if (undoMgr.getUndoStackSize() > 0) {
+ undoMgr.undo();
+ populateLayers();
+ }
+ };
+
+ const clickRedo = function () {
+ if (undoMgr.getRedoStackSize() > 0) {
+ undoMgr.redo();
+ populateLayers();
+ }
+ };
+
+ const clickGroup = function () {
+ // group
+ if (multiselected) {
+ svgCanvas.groupSelectedElements();
+ // ungroup
+ } else if (selectedElement) {
+ svgCanvas.ungroupSelectedElement();
+ }
+ };
+
+ const clickClone = function () {
+ svgCanvas.cloneSelectedElements(20, 20);
+ };
+
+ const clickAlign = function () {
+ const letter = this.id.replace('tool_align', '').charAt(0);
+ svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val());
+ };
+
+ const clickWireframe = function () {
+ $('#tool_wireframe').toggleClass('push_button_pressed tool_button');
+ workarea.toggleClass('wireframe');
+
+ if (supportsNonSS) { return; }
+ let wfRules = $('#wireframe_rules');
+ if (!wfRules.length) {
+ wfRules = $('').appendTo('head');
+ } else {
+ wfRules.empty();
+ }
+
+ updateWireFrame();
+ };
+
+ $('#svg_docprops_container, #svg_prefs_container').draggable({cancel: 'button,fieldset', containment: 'window'});
+
+ let docprops = false;
+ let preferences = false;
+
+ const showDocProperties = function () {
+ if (docprops) { return; }
+ docprops = true;
+
+ // This selects the correct radio button by using the array notation
+ $('#image_save_opts input').val([$.pref('img_save')]);
+
+ // update resolution option with actual resolution
+ const res = svgCanvas.getResolution();
+ if (curConfig.baseUnit !== 'px') {
+ res.w = convertUnit(res.w) + curConfig.baseUnit;
+ res.h = convertUnit(res.h) + curConfig.baseUnit;
+ }
+
+ $('#canvas_width').val(res.w);
+ $('#canvas_height').val(res.h);
+ $('#canvas_title').val(svgCanvas.getDocumentTitle());
+
+ $('#svg_docprops').show();
+ };
+
+ const showPreferences = function () {
+ if (preferences) { return; }
+ preferences = true;
+ $('#main_menu').hide();
+
+ // Update background color with current one
+ const blocks = $('#bg_blocks div');
+ const curBg = 'cur_background';
+ const canvasBg = curPrefs.bkgd_color;
+ const url = $.pref('bkgd_url');
+ blocks.each(function () {
+ const blk = $(this);
+ const isBg = blk.css('background-color') === canvasBg;
+ blk.toggleClass(curBg, isBg);
+ if (isBg) { $('#canvas_bg_url').removeClass(curBg); }
+ });
+ if (!canvasBg) { blocks.eq(0).addClass(curBg); }
+ if (url) {
+ $('#canvas_bg_url').val(url);
+ }
+ $('#grid_snapping_on').prop('checked', curConfig.gridSnapping);
+ $('#grid_snapping_step').attr('value', curConfig.snappingStep);
+ $('#grid_color').attr('value', curConfig.gridColor);
+
+ $('#svg_prefs').show();
+ };
+
+ const hideSourceEditor = function () {
+ $('#svg_source_editor').hide();
+ editingsource = false;
+ $('#svg_source_textarea').blur();
+ };
+
+ const saveSourceEditor = function () {
+ if (!editingsource) { return; }
+
+ const saveChanges = function () {
+ svgCanvas.clearSelection();
+ hideSourceEditor();
+ zoomImage();
+ populateLayers();
+ updateTitle();
+ prepPaints();
};
- var winWh = {width: $(window).width(), height: $(window).height()};
+ if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) {
+ $.confirm(uiStrings.notification.QerrorsRevertToSource, function (ok) {
+ if (!ok) { return false; }
+ saveChanges();
+ });
+ } else {
+ saveChanges();
+ }
+ setSelectMode();
+ };
- // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
- if (svgedit.browser.isIE()) {
- (function () {
- resetScrollPos = function () {
- if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) {
- workarea[0].scrollLeft = curScrollPos.left;
- workarea[0].scrollTop = curScrollPos.top;
- }
- };
+ const hideDocProperties = function () {
+ $('#svg_docprops').hide();
+ $('#canvas_width,#canvas_height').removeAttr('disabled');
+ $('#resolution')[0].selectedIndex = 0;
+ $('#image_save_opts input').val([$.pref('img_save')]);
+ docprops = false;
+ };
+ const hidePreferences = function () {
+ $('#svg_prefs').hide();
+ preferences = false;
+ };
+
+ const saveDocProperties = function () {
+ // set title
+ const newTitle = $('#canvas_title').val();
+ updateTitle(newTitle);
+ svgCanvas.setDocumentTitle(newTitle);
+
+ // update resolution
+ const width = $('#canvas_width'), w = width.val();
+ const height = $('#canvas_height'), h = height.val();
+
+ if (w !== 'fit' && !isValidUnit('width', w)) {
+ $.alert(uiStrings.notification.invalidAttrValGiven);
+ width.parent().addClass('error');
+ return false;
+ }
+
+ width.parent().removeClass('error');
+
+ if (h !== 'fit' && !isValidUnit('height', h)) {
+ $.alert(uiStrings.notification.invalidAttrValGiven);
+ height.parent().addClass('error');
+ return false;
+ }
+
+ height.parent().removeClass('error');
+
+ if (!svgCanvas.setResolution(w, h)) {
+ $.alert(uiStrings.notification.noContentToFitTo);
+ return false;
+ }
+
+ // Set image save option
+ $.pref('img_save', $('#image_save_opts :checked').val());
+ updateCanvas();
+ hideDocProperties();
+ };
+
+ const savePreferences = editor.savePreferences = function () {
+ // Set background
+ const color = $('#bg_blocks div.cur_background').css('background-color') || '#FFF';
+ setBackground(color, $('#canvas_bg_url').val());
+
+ // set language
+ const lang = $('#lang_select').val();
+ if (lang !== $.pref('lang')) {
+ editor.putLocale(lang, goodLangs);
+ }
+
+ // set icon size
+ setIconSize($('#iconsize').val());
+
+ // set grid setting
+ curConfig.gridSnapping = $('#grid_snapping_on')[0].checked;
+ curConfig.snappingStep = $('#grid_snapping_step').val();
+ curConfig.gridColor = $('#grid_color').val();
+ curConfig.showRulers = $('#show_rulers')[0].checked;
+
+ $('#rulers').toggle(curConfig.showRulers);
+ if (curConfig.showRulers) { updateRulers(); }
+ curConfig.baseUnit = $('#base_unit').val();
+
+ svgCanvas.setConfig(curConfig);
+
+ updateCanvas();
+ hidePreferences();
+ };
+
+ let resetScrollPos = $.noop;
+
+ const cancelOverlays = function () {
+ $('#dialog_box').hide();
+ if (!editingsource && !docprops && !preferences) {
+ if (curContext) {
+ svgCanvas.leaveContext();
+ }
+ return;
+ }
+
+ if (editingsource) {
+ if (origSource !== $('#svg_source_textarea').val()) {
+ $.confirm(uiStrings.notification.QignoreSourceChanges, function (ok) {
+ if (ok) { hideSourceEditor(); }
+ });
+ } else {
+ hideSourceEditor();
+ }
+ } else if (docprops) {
+ hideDocProperties();
+ } else if (preferences) {
+ hidePreferences();
+ }
+ resetScrollPos();
+ };
+
+ const winWh = {width: $(window).width(), height: $(window).height()};
+
+ // Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
+ if (isIE()) {
+ (() => {
+ resetScrollPos = function () {
+ if (workarea[0].scrollLeft === 0 && workarea[0].scrollTop === 0) {
+ workarea[0].scrollLeft = curScrollPos.left;
+ workarea[0].scrollTop = curScrollPos.top;
+ }
+ };
+
+ curScrollPos = {
+ left: workarea[0].scrollLeft,
+ top: workarea[0].scrollTop
+ };
+
+ $(window).resize(resetScrollPos);
+ editor.ready(function () {
+ // TODO: Find better way to detect when to do this to minimize
+ // flickering effect
+ setTimeout(function () {
+ resetScrollPos();
+ }, 500);
+ });
+
+ workarea.scroll(function () {
curScrollPos = {
left: workarea[0].scrollLeft,
top: workarea[0].scrollTop
};
-
- $(window).resize(resetScrollPos);
- editor.ready(function () {
- // TODO: Find better way to detect when to do this to minimize
- // flickering effect
- setTimeout(function () {
- resetScrollPos();
- }, 500);
- });
-
- workarea.scroll(function () {
- curScrollPos = {
- left: workarea[0].scrollLeft,
- top: workarea[0].scrollTop
- };
- });
- }());
- }
-
- $(window).resize(function (evt) {
- $.each(winWh, function (type, val) {
- var curval = $(window)[type]();
- workarea[0]['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
- winWh[type] = curval;
});
- setFlyoutPositions();
+ })();
+ }
+
+ $(window).resize(function (evt) {
+ $.each(winWh, function (type, val) {
+ const curval = $(window)[type]();
+ workarea[0]['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
+ winWh[type] = curval;
+ });
+ setFlyoutPositions();
+ });
+
+ (() => {
+ workarea.scroll(function () {
+ // TODO: jQuery's scrollLeft/Top() wouldn't require a null check
+ if ($('#ruler_x').length) {
+ $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;
+ }
+ if ($('#ruler_y').length) {
+ $('#ruler_y')[0].scrollTop = workarea[0].scrollTop;
+ }
+ });
+ })();
+
+ $('#url_notice').click(function () {
+ $.alert(this.title);
+ });
+
+ $('#change_image_url').click(promptImgURL);
+
+ // added these event handlers for all the push buttons so they
+ // behave more like buttons being pressed-in and not images
+ (function () {
+ const toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom'];
+ const curClass = 'tool_button_current';
+
+ let allTools = '';
+
+ $.each(toolnames, function (i, item) {
+ allTools += (i ? ',' : '') + '#tool_' + item;
});
- (function () {
- workarea.scroll(function () {
- // TODO: jQuery's scrollLeft/Top() wouldn't require a null check
- if ($('#ruler_x').length !== 0) {
- $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;
- }
- if ($('#ruler_y').length !== 0) {
- $('#ruler_y')[0].scrollTop = workarea[0].scrollTop;
- }
- });
- }());
-
- $('#url_notice').click(function () {
- $.alert(this.title);
+ $(allTools).mousedown(function () {
+ $(this).addClass(curClass);
+ }).bind('mousedown mouseout', function () {
+ $(this).removeClass(curClass);
});
- $('#change_image_url').click(promptImgURL);
+ $('#tool_undo, #tool_redo').mousedown(function () {
+ if (!$(this).hasClass('disabled')) { $(this).addClass(curClass); }
+ }).bind('mousedown mouseout', function () {
+ $(this).removeClass(curClass);
+ });
+ }());
- // added these event handlers for all the push buttons so they
- // behave more like buttons being pressed-in and not images
- (function () {
- var toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom'];
- var allTools = '';
- var curClass = 'tool_button_current';
-
- $.each(toolnames, function (i, item) {
- allTools += (i ? ',' : '') + '#tool_' + item;
- });
-
- $(allTools).mousedown(function () {
- $(this).addClass(curClass);
- }).bind('mousedown mouseout', function () {
- $(this).removeClass(curClass);
- });
-
- $('#tool_undo, #tool_redo').mousedown(function () {
- if (!$(this).hasClass('disabled')) { $(this).addClass(curClass); }
- }).bind('mousedown mouseout', function () {
- $(this).removeClass(curClass);
- });
- }());
-
- // switch modifier key in tooltips if mac
- // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta
- // in Opera and Chrome
- if (svgedit.browser.isMac() && !window.opera) {
- var shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone'];
- i = shortcutButtons.length;
- while (i--) {
- var button = document.getElementById(shortcutButtons[i]);
- if (button) {
- var title = button.title;
- var index = title.indexOf('Ctrl+');
- button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join('');
- }
+ // switch modifier key in tooltips if mac
+ // NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta
+ // in Opera and Chrome
+ if (isMac() && !window.opera) {
+ const shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone'];
+ let i = shortcutButtons.length;
+ while (i--) {
+ const button = document.getElementById(shortcutButtons[i]);
+ if (button) {
+ const {title} = button;
+ const index = title.indexOf('Ctrl+');
+ button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join('');
}
}
+ }
- // TODO: go back to the color boxes having white background-color and then setting
- // background-image to none.png (otherwise partially transparent gradients look weird)
- var colorPicker = function (elem) {
- var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill';
- // var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
- var paint = paintBox[picker].paint;
- var title = (picker === 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity');
- // var was_none = false; // Currently unused
- var pos = elem.offset();
- $('#color_picker')
- .draggable({cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window'})
- .css(curConfig.colorPickerCSS || {'left': pos.left - 140, 'bottom': 40})
- .jGraduate(
- {
- paint: paint,
- window: { pickerTitle: title },
- images: { clientPath: curConfig.jGraduatePath },
- newstop: 'inverse'
- },
- function (p) {
- paint = new $.jGraduate.Paint(p);
- paintBox[picker].setPaint(paint);
- svgCanvas.setPaint(picker, paint);
- $('#color_picker').hide();
- },
- function () {
- $('#color_picker').hide();
- }
- );
- };
+ // TODO: go back to the color boxes having white background-color and then setting
+ // background-image to none.png (otherwise partially transparent gradients look weird)
+ const colorPicker = function (elem) {
+ const picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill';
+ // const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
+ const title = (picker === 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity');
+ // let wasNone = false; // Currently unused
+ const pos = elem.offset();
+ let {paint} = paintBox[picker];
+ $('#color_picker')
+ .draggable({cancel: '.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window'})
+ .css(curConfig.colorPickerCSS || {'left': pos.left - 140, 'bottom': 40})
+ .jGraduate(
+ {
+ paint,
+ window: { pickerTitle: title },
+ images: { clientPath: curConfig.jGraduatePath },
+ newstop: 'inverse'
+ },
+ function (p) {
+ paint = new $.jGraduate.Paint(p);
+ paintBox[picker].setPaint(paint);
+ svgCanvas.setPaint(picker, paint);
+ $('#color_picker').hide();
+ },
+ function () {
+ $('#color_picker').hide();
+ }
+ );
+ };
- var PaintBox = function (container, type) {
- var paintColor, paintOpacity,
- cur = curConfig[type === 'fill' ? 'initFill' : 'initStroke'];
- // set up gradients to be used for the buttons
- var svgdocbox = new DOMParser().parseFromString(
- '
', 'text/xml');
- var docElem = svgdocbox.documentElement;
- docElem = $(container)[0].appendChild(document.importNode(docElem, true));
- docElem.setAttribute('width', 16.5);
+ let docElem = svgdocbox.documentElement;
+ docElem = $(container)[0].appendChild(document.importNode(docElem, true));
+ docElem.setAttribute('width', 16.5);
- this.rect = docElem.firstChild;
- this.defs = docElem.getElementsByTagName('defs')[0];
- this.grad = this.defs.firstChild;
- this.paint = new $.jGraduate.Paint({solidColor: cur.color});
- this.type = type;
+ this.rect = docElem.firstChild;
+ this.defs = docElem.getElementsByTagName('defs')[0];
+ this.grad = this.defs.firstChild;
+ this.paint = new $.jGraduate.Paint({solidColor: cur.color});
+ this.type = type;
- this.setPaint = function (paint, apply) {
- this.paint = paint;
+ this.setPaint = function (paint, apply) {
+ this.paint = paint;
- var fillAttr = 'none';
- var ptype = paint.type;
- var opac = paint.alpha / 100;
+ const ptype = paint.type;
+ const opac = paint.alpha / 100;
- switch (ptype) {
- case 'solidColor':
- fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype];
- break;
- case 'linearGradient':
- case 'radialGradient':
- this.defs.removeChild(this.grad);
- this.grad = this.defs.appendChild(paint[ptype]);
- var id = this.grad.id = 'gradbox_' + this.type;
- fillAttr = 'url(#' + id + ')';
- break;
- }
+ let fillAttr = 'none';
+ switch (ptype) {
+ case 'solidColor':
+ fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype];
+ break;
+ case 'linearGradient':
+ case 'radialGradient':
+ this.defs.removeChild(this.grad);
+ this.grad = this.defs.appendChild(paint[ptype]);
+ const id = this.grad.id = 'gradbox_' + this.type;
+ fillAttr = 'url(#' + id + ')';
+ break;
+ }
- this.rect.setAttribute('fill', fillAttr);
- this.rect.setAttribute('opacity', opac);
+ this.rect.setAttribute('fill', fillAttr);
+ this.rect.setAttribute('opacity', opac);
- if (apply) {
- svgCanvas.setColor(this.type, paintColor, true);
- svgCanvas.setPaintOpacity(this.type, paintOpacity, true);
- }
- };
-
- this.update = function (apply) {
- if (!selectedElement) { return; }
- var i, len;
- var type = this.type;
- switch (selectedElement.tagName) {
- case 'use':
- case 'image':
- case 'foreignObject':
- // These elements don't have fill or stroke, so don't change
- // the current value
- return;
- case 'g':
- case 'a':
- var gPaint = null;
-
- var childs = selectedElement.getElementsByTagName('*');
- for (i = 0, len = childs.length; i < len; i++) {
- var elem = childs[i];
- var p = elem.getAttribute(type);
- if (i === 0) {
- gPaint = p;
- } else if (gPaint !== p) {
- gPaint = null;
- break;
- }
- }
-
- if (gPaint === null) {
- // No common color, don't update anything
- paintColor = null;
- return;
- }
- paintColor = gPaint;
- paintOpacity = 1;
- break;
- default:
- paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity'));
- if (isNaN(paintOpacity)) {
- paintOpacity = 1.0;
- }
-
- var defColor = type === 'fill' ? 'black' : 'none';
- paintColor = selectedElement.getAttribute(type) || defColor;
- }
-
- if (apply) {
- svgCanvas.setColor(type, paintColor, true);
- svgCanvas.setPaintOpacity(type, paintOpacity, true);
- }
-
- paintOpacity *= 100;
-
- var paint = getPaint(paintColor, paintOpacity, type);
- // update the rect inside #fill_color/#stroke_color
- this.setPaint(paint);
- };
-
- this.prep = function () {
- var ptype = this.paint.type;
-
- switch (ptype) {
- case 'linearGradient':
- case 'radialGradient':
- var paint = new $.jGraduate.Paint({copy: this.paint});
- svgCanvas.setPaint(type, paint);
- break;
- }
- };
+ if (apply) {
+ svgCanvas.setColor(this.type, paintColor, true);
+ svgCanvas.setPaintOpacity(this.type, paintOpacity, true);
+ }
};
- paintBox.fill = new PaintBox('#fill_color', 'fill');
- paintBox.stroke = new PaintBox('#stroke_color', 'stroke');
+ this.update = function (apply) {
+ if (!selectedElement) { return; }
- $('#stroke_width').val(curConfig.initStroke.width);
- $('#group_opacity').val(curConfig.initOpacity * 100);
+ const {type} = this;
+ switch (selectedElement.tagName) {
+ case 'use':
+ case 'image':
+ case 'foreignObject':
+ // These elements don't have fill or stroke, so don't change
+ // the current value
+ return;
+ case 'g':
+ case 'a': {
+ const childs = selectedElement.getElementsByTagName('*');
- // Use this SVG elem to test vectorEffect support
- var testEl = paintBox.fill.rect.cloneNode(false);
- testEl.setAttribute('style', 'vector-effect:non-scaling-stroke');
- supportsNonSS = (testEl.style.vectorEffect === 'non-scaling-stroke');
- testEl.removeAttribute('style');
- var svgdocbox = paintBox.fill.rect.ownerDocument;
- // Use this to test support for blur element. Seems to work to test support in Webkit
- var blurTest = svgdocbox.createElementNS(svgedit.NS.SVG, 'feGaussianBlur');
- if (blurTest.stdDeviationX === undefined) {
- $('#tool_blur').hide();
- }
- $(blurTest).remove();
-
- // Test for zoom icon support
- (function () {
- var pre = '-' + uaPrefix.toLowerCase() + '-zoom-';
- var zoom = pre + 'in';
- workarea.css('cursor', zoom);
- if (workarea.css('cursor') === zoom) {
- zoomInIcon = zoom;
- zoomOutIcon = pre + 'out';
- }
- workarea.css('cursor', 'auto');
- }());
-
- // Test for embedImage support (use timeout to not interfere with page load)
- setTimeout(function () {
- svgCanvas.embedImage('images/logo.png', function (datauri) {
- if (!datauri) {
- // Disable option
- $('#image_save_opts [value=embed]').attr('disabled', 'disabled');
- $('#image_save_opts input').val(['ref']);
- $.pref('img_save', 'ref');
- $('#image_opt_embed').css('color', '#666').attr('title', uiStrings.notification.featNotSupported);
+ let gPaint = null;
+ for (let i = 0, len = childs.length; i < len; i++) {
+ const elem = childs[i];
+ const p = elem.getAttribute(type);
+ if (i === 0) {
+ gPaint = p;
+ } else if (gPaint !== p) {
+ gPaint = null;
+ break;
+ }
}
- });
- }, 1000);
- $('#fill_color, #tool_fill .icon_label').click(function () {
- colorPicker($('#fill_color'));
- updateToolButtonState();
- });
-
- $('#stroke_color, #tool_stroke .icon_label').click(function () {
- colorPicker($('#stroke_color'));
- updateToolButtonState();
- });
-
- $('#group_opacityLabel').click(function () {
- $('#opacity_dropdown button').mousedown();
- $(window).mouseup();
- });
-
- $('#zoomLabel').click(function () {
- $('#zoom_dropdown button').mousedown();
- $(window).mouseup();
- });
-
- $('#tool_move_top').mousedown(function (evt) {
- $('#tools_stacking').show();
- evt.preventDefault();
- });
-
- $('.layer_button').mousedown(function () {
- $(this).addClass('layer_buttonpressed');
- }).mouseout(function () {
- $(this).removeClass('layer_buttonpressed');
- }).mouseup(function () {
- $(this).removeClass('layer_buttonpressed');
- });
-
- $('.push_button').mousedown(function () {
- if (!$(this).hasClass('disabled')) {
- $(this).addClass('push_button_pressed').removeClass('push_button');
- }
- }).mouseout(function () {
- $(this).removeClass('push_button_pressed').addClass('push_button');
- }).mouseup(function () {
- $(this).removeClass('push_button_pressed').addClass('push_button');
- });
-
- // ask for a layer name
- $('#layer_new').click(function () {
- var uniqName,
- i = svgCanvas.getCurrentDrawing().getNumLayers();
- do {
- uniqName = uiStrings.layers.layer + ' ' + (++i);
- } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName));
-
- $.prompt(uiStrings.notification.enterUniqueLayerName, uniqName, function (newName) {
- if (!newName) { return; }
- if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
- $.alert(uiStrings.notification.dupeLayerName);
+ if (gPaint === null) {
+ // No common color, don't update anything
+ paintColor = null;
return;
}
- svgCanvas.createLayer(newName);
- updateContextPanel();
- populateLayers();
- });
- });
-
- function deleteLayer () {
- if (svgCanvas.deleteCurrentLayer()) {
- updateContextPanel();
- populateLayers();
- // This matches what SvgCanvas does
- // TODO: make this behavior less brittle (svg-editor should get which
- // layer is selected from the canvas and then select that one in the UI)
- $('#layerlist tr.layer').removeClass('layersel');
- $('#layerlist tr.layer:first').addClass('layersel');
- }
- }
-
- function cloneLayer () {
- var name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';
-
- $.prompt(uiStrings.notification.enterUniqueLayerName, name, function (newName) {
- if (!newName) { return; }
- if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
- $.alert(uiStrings.notification.dupeLayerName);
- return;
+ paintColor = gPaint;
+ paintOpacity = 1;
+ break;
+ } default:
+ paintOpacity = parseFloat(selectedElement.getAttribute(type + '-opacity'));
+ if (isNaN(paintOpacity)) {
+ paintOpacity = 1.0;
}
- svgCanvas.cloneLayer(newName);
- updateContextPanel();
- populateLayers();
- });
- }
- function mergeLayer () {
- if ($('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) {
+ const defColor = type === 'fill' ? 'black' : 'none';
+ paintColor = selectedElement.getAttribute(type) || defColor;
+ }
+
+ if (apply) {
+ svgCanvas.setColor(type, paintColor, true);
+ svgCanvas.setPaintOpacity(type, paintOpacity, true);
+ }
+
+ paintOpacity *= 100;
+
+ const paint = getPaint(paintColor, paintOpacity, type);
+ // update the rect inside #fill_color/#stroke_color
+ this.setPaint(paint);
+ };
+
+ this.prep = function () {
+ const ptype = this.paint.type;
+
+ switch (ptype) {
+ case 'linearGradient':
+ case 'radialGradient':
+ const paint = new $.jGraduate.Paint({copy: this.paint});
+ svgCanvas.setPaint(type, paint);
+ break;
+ }
+ };
+ };
+
+ paintBox.fill = new PaintBox('#fill_color', 'fill');
+ paintBox.stroke = new PaintBox('#stroke_color', 'stroke');
+
+ $('#stroke_width').val(curConfig.initStroke.width);
+ $('#group_opacity').val(curConfig.initOpacity * 100);
+
+ // Use this SVG elem to test vectorEffect support
+ const testEl = paintBox.fill.rect.cloneNode(false);
+ testEl.setAttribute('style', 'vector-effect:non-scaling-stroke');
+ const supportsNonSS = (testEl.style.vectorEffect === 'non-scaling-stroke');
+ testEl.removeAttribute('style');
+ const svgdocbox = paintBox.fill.rect.ownerDocument;
+ // Use this to test support for blur element. Seems to work to test support in Webkit
+ const blurTest = svgdocbox.createElementNS(NS.SVG, 'feGaussianBlur');
+ if (blurTest.stdDeviationX === undefined) {
+ $('#tool_blur').hide();
+ }
+ $(blurTest).remove();
+
+ // Test for zoom icon support
+ (function () {
+ const pre = '-' + uaPrefix.toLowerCase() + '-zoom-';
+ const zoom = pre + 'in';
+ workarea.css('cursor', zoom);
+ if (workarea.css('cursor') === zoom) {
+ zoomInIcon = zoom;
+ zoomOutIcon = pre + 'out';
+ }
+ workarea.css('cursor', 'auto');
+ }());
+
+ // Test for embedImage support (use timeout to not interfere with page load)
+ setTimeout(function () {
+ svgCanvas.embedImage('images/logo.png', function (datauri) {
+ if (!datauri) {
+ // Disable option
+ $('#image_save_opts [value=embed]').attr('disabled', 'disabled');
+ $('#image_save_opts input').val(['ref']);
+ $.pref('img_save', 'ref');
+ $('#image_opt_embed').css('color', '#666').attr('title', uiStrings.notification.featNotSupported);
+ }
+ });
+ }, 1000);
+
+ $('#fill_color, #tool_fill .icon_label').click(function () {
+ colorPicker($('#fill_color'));
+ updateToolButtonState();
+ });
+
+ $('#stroke_color, #tool_stroke .icon_label').click(function () {
+ colorPicker($('#stroke_color'));
+ updateToolButtonState();
+ });
+
+ $('#group_opacityLabel').click(function () {
+ $('#opacity_dropdown button').mousedown();
+ $(window).mouseup();
+ });
+
+ $('#zoomLabel').click(function () {
+ $('#zoom_dropdown button').mousedown();
+ $(window).mouseup();
+ });
+
+ $('#tool_move_top').mousedown(function (evt) {
+ $('#tools_stacking').show();
+ evt.preventDefault();
+ });
+
+ $('.layer_button').mousedown(function () {
+ $(this).addClass('layer_buttonpressed');
+ }).mouseout(function () {
+ $(this).removeClass('layer_buttonpressed');
+ }).mouseup(function () {
+ $(this).removeClass('layer_buttonpressed');
+ });
+
+ $('.push_button').mousedown(function () {
+ if (!$(this).hasClass('disabled')) {
+ $(this).addClass('push_button_pressed').removeClass('push_button');
+ }
+ }).mouseout(function () {
+ $(this).removeClass('push_button_pressed').addClass('push_button');
+ }).mouseup(function () {
+ $(this).removeClass('push_button_pressed').addClass('push_button');
+ });
+
+ // ask for a layer name
+ $('#layer_new').click(function () {
+ let uniqName,
+ i = svgCanvas.getCurrentDrawing().getNumLayers();
+ do {
+ uniqName = uiStrings.layers.layer + ' ' + (++i);
+ } while (svgCanvas.getCurrentDrawing().hasLayer(uniqName));
+
+ $.prompt(uiStrings.notification.enterUniqueLayerName, uniqName, function (newName) {
+ if (!newName) { return; }
+ if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
+ $.alert(uiStrings.notification.dupeLayerName);
return;
}
- svgCanvas.mergeLayer();
+ svgCanvas.createLayer(newName);
updateContextPanel();
populateLayers();
+ });
+ });
+
+ function deleteLayer () {
+ if (svgCanvas.deleteCurrentLayer()) {
+ updateContextPanel();
+ populateLayers();
+ // This matches what SvgCanvas does
+ // TODO: make this behavior less brittle (svg-editor should get which
+ // layer is selected from the canvas and then select that one in the UI)
+ $('#layerlist tr.layer').removeClass('layersel');
+ $('#layerlist tr.layer:first').addClass('layersel');
}
+ }
- function moveLayer (pos) {
- var curIndex = $('#layerlist tr.layersel').index();
- var total = svgCanvas.getCurrentDrawing().getNumLayers();
- if (curIndex > 0 || curIndex < total - 1) {
- curIndex += pos;
- svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
- populateLayers();
+ function cloneLayer () {
+ const name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';
+
+ $.prompt(uiStrings.notification.enterUniqueLayerName, name, function (newName) {
+ if (!newName) { return; }
+ if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
+ $.alert(uiStrings.notification.dupeLayerName);
+ return;
}
+ svgCanvas.cloneLayer(newName);
+ updateContextPanel();
+ populateLayers();
+ });
+ }
+
+ function mergeLayer () {
+ if ($('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) {
+ return;
}
+ svgCanvas.mergeLayer();
+ updateContextPanel();
+ populateLayers();
+ }
- $('#layer_delete').click(deleteLayer);
+ function moveLayer (pos) {
+ const total = svgCanvas.getCurrentDrawing().getNumLayers();
- $('#layer_up').click(function () {
- moveLayer(-1);
- });
+ let curIndex = $('#layerlist tr.layersel').index();
+ if (curIndex > 0 || curIndex < total - 1) {
+ curIndex += pos;
+ svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
+ populateLayers();
+ }
+ }
- $('#layer_down').click(function () {
- moveLayer(1);
- });
+ $('#layer_delete').click(deleteLayer);
- $('#layer_rename').click(function () {
- // var curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
- var oldName = $('#layerlist tr.layersel td.layername').text();
- $.prompt(uiStrings.notification.enterNewLayerName, '', function (newName) {
- if (!newName) { return; }
- if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) {
- $.alert(uiStrings.notification.layerHasThatName);
- return;
- }
+ $('#layer_up').click(() => {
+ moveLayer(-1);
+ });
- svgCanvas.renameCurrentLayer(newName);
- populateLayers();
- });
- });
+ $('#layer_down').click(() => {
+ moveLayer(1);
+ });
- var SIDEPANEL_MAXWIDTH = 300;
- var SIDEPANEL_OPENWIDTH = 150;
- var sidedrag = -1, sidedragging = false, allowmove = false;
-
- var changeSidePanelWidth = function (delta) {
- var rulerX = $('#ruler_x');
- $('#sidepanels').width('+=' + delta);
- $('#layerpanel').width('+=' + delta);
- rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta);
- workarea.css('right', parseInt(workarea.css('right'), 10) + delta);
- svgCanvas.runExtensions('workareaResized');
- };
-
- var resizeSidePanel = function (evt) {
- if (!allowmove) { return; }
- if (sidedrag === -1) { return; }
- sidedragging = true;
- var deltaX = sidedrag - evt.pageX;
- var sideWidth = $('#sidepanels').width();
- if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {
- deltaX = SIDEPANEL_MAXWIDTH - sideWidth;
- sideWidth = SIDEPANEL_MAXWIDTH;
- } else if (sideWidth + deltaX < 2) {
- deltaX = 2 - sideWidth;
- sideWidth = 2;
+ $('#layer_rename').click(function () {
+ // const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
+ const oldName = $('#layerlist tr.layersel td.layername').text();
+ $.prompt(uiStrings.notification.enterNewLayerName, '', function (newName) {
+ if (!newName) { return; }
+ if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) {
+ $.alert(uiStrings.notification.layerHasThatName);
+ return;
}
- if (deltaX === 0) { return; }
- sidedrag -= 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
- var toggleSidePanel = function (close) {
- var w = $('#sidepanels').width();
- var deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w;
- changeSidePanelWidth(deltaX);
- };
+ svgCanvas.renameCurrentLayer(newName);
+ populateLayers();
+ });
+ });
- $('#sidepanel_handle')
- .mousedown(function (evt) {
- sidedrag = evt.pageX;
- $(window).mousemove(resizeSidePanel);
- allowmove = false;
- // Silly hack for Chrome, which always runs mousemove right after mousedown
- setTimeout(function () {
- allowmove = true;
- }, 20);
- })
- .mouseup(function (evt) {
- if (!sidedragging) { toggleSidePanel(); }
- sidedrag = -1;
- sidedragging = false;
- });
+ const SIDEPANEL_MAXWIDTH = 300;
+ const SIDEPANEL_OPENWIDTH = 150;
+ let sidedrag = -1, sidedragging = false, allowmove = false;
- $(window).mouseup(function () {
+ const changeSidePanelWidth = function (delta) {
+ const rulerX = $('#ruler_x');
+ $('#sidepanels').width('+=' + delta);
+ $('#layerpanel').width('+=' + delta);
+ rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta);
+ workarea.css('right', parseInt(workarea.css('right'), 10) + delta);
+ svgCanvas.runExtensions('workareaResized');
+ };
+
+ const resizeSidePanel = function (evt) {
+ if (!allowmove) { return; }
+ if (sidedrag === -1) { return; }
+ sidedragging = true;
+ let deltaX = sidedrag - evt.pageX;
+ let sideWidth = $('#sidepanels').width();
+ if (sideWidth + deltaX > SIDEPANEL_MAXWIDTH) {
+ deltaX = SIDEPANEL_MAXWIDTH - sideWidth;
+ sideWidth = SIDEPANEL_MAXWIDTH;
+ } else if (sideWidth + deltaX < 2) {
+ deltaX = 2 - sideWidth;
+ sideWidth = 2;
+ }
+ if (deltaX === 0) { return; }
+ sidedrag -= 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
+ const toggleSidePanel = function (close) {
+ const w = $('#sidepanels').width();
+ const deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w;
+ changeSidePanelWidth(deltaX);
+ };
+
+ $('#sidepanel_handle')
+ .mousedown(function (evt) {
+ sidedrag = evt.pageX;
+ $(window).mousemove(resizeSidePanel);
+ allowmove = false;
+ // Silly hack for Chrome, which always runs mousemove right after mousedown
+ setTimeout(function () {
+ allowmove = true;
+ }, 20);
+ })
+ .mouseup(function (evt) {
+ if (!sidedragging) { toggleSidePanel(); }
sidedrag = -1;
sidedragging = false;
- $('#svg_editor').unbind('mousemove', resizeSidePanel);
});
- populateLayers();
+ $(window).mouseup(function () {
+ sidedrag = -1;
+ sidedragging = false;
+ $('#svg_editor').unbind('mousemove', resizeSidePanel);
+ });
- // function changeResolution (x,y) {
- // var zoom = svgCanvas.getResolution().zoom;
- // setResolution(x * zoom, y * zoom);
- // }
+ populateLayers();
- var centerCanvas = function () {
- // this centers the canvas vertically in the workarea (horizontal handled in CSS)
- workarea.css('line-height', workarea.height() + 'px');
- };
+ // function changeResolution (x,y) {
+ // const {zoom} = svgCanvas.getResolution();
+ // setResolution(x * zoom, y * zoom);
+ // }
- $(window).bind('load resize', centerCanvas);
+ const centerCanvas = () => {
+ // this centers the canvas vertically in the workarea (horizontal handled in CSS)
+ workarea.css('line-height', workarea.height() + 'px');
+ };
- function stepFontSize (elem, step) {
- var origVal = Number(elem.value);
- var sugVal = origVal + step;
- var increasing = sugVal >= origVal;
- if (step === 0) { return origVal; }
+ $(window).bind('load resize', centerCanvas);
- if (origVal >= 24) {
- if (increasing) {
- return Math.round(origVal * 1.1);
- }
- return Math.round(origVal / 1.1);
+ function stepFontSize (elem, step) {
+ const origVal = Number(elem.value);
+ const sugVal = origVal + step;
+ const increasing = sugVal >= origVal;
+ if (step === 0) { return origVal; }
+
+ if (origVal >= 24) {
+ if (increasing) {
+ return Math.round(origVal * 1.1);
}
- if (origVal <= 1) {
- if (increasing) {
- return origVal * 2;
- }
- return origVal / 2;
- }
- return sugVal;
+ return Math.round(origVal / 1.1);
}
-
- function stepZoom (elem, step) {
- var origVal = Number(elem.value);
- if (origVal === 0) { return 100; }
- var sugVal = origVal + step;
- if (step === 0) { return origVal; }
-
- if (origVal >= 100) {
- return sugVal;
- }
- if (sugVal >= origVal) {
+ if (origVal <= 1) {
+ if (increasing) {
return origVal * 2;
}
return origVal / 2;
}
+ return sugVal;
+ }
- // function setResolution (w, h, center) {
- // updateCanvas();
- // // w -= 0; h -= 0;
- // // $('#svgcanvas').css({'width': w, 'height': h});
- // // $('#canvas_width').val(w);
- // // $('#canvas_height').val(h);
- // //
- // // if (center) {
- // // var wArea = workarea;
- // // var scrollY = h/2 - wArea.height()/2;
- // // var scrollX = w/2 - wArea.width()/2;
- // // wArea[0].scrollTop = scrollY;
- // // wArea[0].scrollLeft = scrollX;
- // // }
- // }
+ function stepZoom (elem, step) {
+ const origVal = Number(elem.value);
+ if (origVal === 0) { return 100; }
+ const sugVal = origVal + step;
+ if (step === 0) { return origVal; }
- $('#resolution').change(function () {
- var wh = $('#canvas_width,#canvas_height');
- if (!this.selectedIndex) {
- if ($('#canvas_width').val() === 'fit') {
- wh.removeAttr('disabled').val(100);
+ if (origVal >= 100) {
+ return sugVal;
+ }
+ if (sugVal >= origVal) {
+ return origVal * 2;
+ }
+ return origVal / 2;
+ }
+
+ // function setResolution (w, h, center) {
+ // updateCanvas();
+ // // w -= 0; h -= 0;
+ // // $('#svgcanvas').css({'width': w, 'height': h});
+ // // $('#canvas_width').val(w);
+ // // $('#canvas_height').val(h);
+ // //
+ // // if (center) {
+ // // const wArea = workarea;
+ // // const scrollY = h/2 - wArea.height()/2;
+ // // const scrollX = w/2 - wArea.width()/2;
+ // // wArea[0].scrollTop = scrollY;
+ // // wArea[0].scrollLeft = scrollX;
+ // // }
+ // }
+
+ $('#resolution').change(function () {
+ const wh = $('#canvas_width,#canvas_height');
+ if (!this.selectedIndex) {
+ if ($('#canvas_width').val() === 'fit') {
+ wh.removeAttr('disabled').val(100);
+ }
+ } else if (this.value === 'content') {
+ wh.val('fit').attr('disabled', 'disabled');
+ } else {
+ const dims = this.value.split('x');
+ $('#canvas_width').val(dims[0]);
+ $('#canvas_height').val(dims[1]);
+ wh.removeAttr('disabled');
+ }
+ });
+
+ // Prevent browser from erroneously repopulating fields
+ $('input,select').attr('autocomplete', 'off');
+
+ // Associate all button actions as well as non-button keyboard shortcuts
+ const Actions = (function () {
+ // sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput]
+ const toolButtons = [
+ {sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]},
+ {sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]},
+ {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true]},
+ {sel: '#tool_rect', fn: clickRect, evt: 'mouseup', key: ['R', true], parent: '#tools_rect', icon: 'rect'},
+ {sel: '#tool_square', fn: clickSquare, evt: 'mouseup', parent: '#tools_rect', icon: 'square'},
+ {sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup', 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_text', fn: clickText, evt: 'click', key: ['T', true]},
+ {sel: '#tool_image', fn: clickImage, evt: 'mouseup'},
+ {sel: '#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true]},
+ {sel: '#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true]},
+ {sel: '#tool_save', fn () {
+ if (editingsource) {
+ saveSourceEditor();
+ } else {
+ clickSave();
}
- } else if (this.value === 'content') {
- wh.val('fit').attr('disabled', 'disabled');
- } else {
- var dims = this.value.split('x');
- $('#canvas_width').val(dims[0]);
- $('#canvas_height').val(dims[1]);
- wh.removeAttr('disabled');
- }
- });
+ }, evt: 'mouseup', key: ['S', true]},
+ {sel: '#tool_export', fn: clickExport, evt: 'mouseup'},
+ {sel: '#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true]},
+ {sel: '#tool_import', fn: clickImport, evt: 'mouseup'},
+ {sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', 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_save', fn: saveSourceEditor, evt: 'click'},
+ {sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'},
+ {sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup'},
+ {sel: '#tool_prefs_save', fn: savePreferences, evt: 'click'},
+ {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_reorient', fn: reorientPath, evt: 'click'},
+ {sel: '#tool_node_link', fn: linkControlPoints, evt: 'click'},
+ {sel: '#tool_node_clone', fn: clonePathNode, evt: 'click'},
+ {sel: '#tool_node_delete', fn: deletePathNode, evt: 'click'},
+ {sel: '#tool_openclose_path', fn: opencloseSubPath, evt: 'click'},
+ {sel: '#tool_add_subpath', fn: addSubPath, evt: 'click'},
+ {sel: '#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]'},
+ {sel: '#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+['},
+ {sel: '#tool_topath', fn: convertToPath, evt: 'click'},
+ {sel: '#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click'},
+ {sel: '#tool_undo', fn: clickUndo, evt: 'click'},
+ {sel: '#tool_redo', fn: clickRedo, evt: 'click'},
+ {sel: '#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['D', true]},
+ {sel: '#tool_group_elements', fn: clickGroup, evt: 'click', key: ['G', true]},
+ {sel: '#tool_ungroup', fn: clickGroup, evt: 'click'},
+ {sel: '#tool_unlink_use', fn: clickGroup, evt: 'click'},
+ {sel: '[id^=tool_align]', fn: clickAlign, evt: 'click'},
+ // these two lines are required to make Opera work properly with the flyout mechanism
+ // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'},
+ // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'},
+ {sel: '#tool_bold', fn: clickBold, evt: 'mousedown'},
+ {sel: '#tool_italic', fn: clickItalic, evt: 'mousedown'},
+ {sel: '#sidepanel_handle', fn: toggleSidePanel, key: ['X']},
+ {sel: '#copy_save_done', fn: cancelOverlays, evt: 'click'},
- // Prevent browser from erroneously repopulating fields
- $('input,select').attr('autocomplete', 'off');
+ // Shortcuts not associated with buttons
- // Associate all button actions as well as non-button keyboard shortcuts
- Actions = (function () {
- // sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput]
- var toolButtons = [
- {sel: '#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]},
- {sel: '#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]},
- {sel: '#tool_line', fn: clickLine, evt: 'click', key: ['L', true]},
- {sel: '#tool_rect', fn: clickRect, evt: 'mouseup', key: ['R', true], parent: '#tools_rect', icon: 'rect'},
- {sel: '#tool_square', fn: clickSquare, evt: 'mouseup', parent: '#tools_rect', icon: 'square'},
- {sel: '#tool_fhrect', fn: clickFHRect, evt: 'mouseup', 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_text', fn: clickText, evt: 'click', key: ['T', true]},
- {sel: '#tool_image', fn: clickImage, evt: 'mouseup'},
- {sel: '#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true]},
- {sel: '#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true]},
- {sel: '#tool_save', fn: function () {
- if (editingsource) {
- saveSourceEditor();
- } else {
- clickSave();
- }
- }, evt: 'mouseup', key: ['S', true]},
- {sel: '#tool_export', fn: clickExport, evt: 'mouseup'},
- {sel: '#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true]},
- {sel: '#tool_import', fn: clickImport, evt: 'mouseup'},
- {sel: '#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', 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_save', fn: saveSourceEditor, evt: 'click'},
- {sel: '#tool_docprops_save', fn: saveDocProperties, evt: 'click'},
- {sel: '#tool_docprops', fn: showDocProperties, evt: 'mouseup'},
- {sel: '#tool_prefs_save', fn: savePreferences, evt: 'click'},
- {sel: '#tool_prefs_option', fn: function () { showPreferences(); return false; }, evt: 'mouseup'},
- {sel: '#tool_delete,#tool_delete_multi', fn: deleteSelected, evt: 'click', key: ['del/backspace', true]},
- {sel: '#tool_reorient', fn: reorientPath, evt: 'click'},
- {sel: '#tool_node_link', fn: linkControlPoints, evt: 'click'},
- {sel: '#tool_node_clone', fn: clonePathNode, evt: 'click'},
- {sel: '#tool_node_delete', fn: deletePathNode, evt: 'click'},
- {sel: '#tool_openclose_path', fn: opencloseSubPath, evt: 'click'},
- {sel: '#tool_add_subpath', fn: addSubPath, evt: 'click'},
- {sel: '#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]'},
- {sel: '#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+['},
- {sel: '#tool_topath', fn: convertToPath, evt: 'click'},
- {sel: '#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click'},
- {sel: '#tool_undo', fn: clickUndo, evt: 'click'},
- {sel: '#tool_redo', fn: clickRedo, evt: 'click'},
- {sel: '#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['D', true]},
- {sel: '#tool_group_elements', fn: clickGroup, evt: 'click', key: ['G', true]},
- {sel: '#tool_ungroup', fn: clickGroup, evt: 'click'},
- {sel: '#tool_unlink_use', fn: clickGroup, evt: 'click'},
- {sel: '[id^=tool_align]', fn: clickAlign, evt: 'click'},
- // these two lines are required to make Opera work properly with the flyout mechanism
- // {sel: '#tools_rect_show', fn: clickRect, evt: 'click'},
- // {sel: '#tools_ellipse_show', fn: clickEllipse, evt: 'click'},
- {sel: '#tool_bold', fn: clickBold, evt: 'mousedown'},
- {sel: '#tool_italic', fn: clickItalic, evt: 'mousedown'},
- {sel: '#sidepanel_handle', fn: toggleSidePanel, key: ['X']},
- {sel: '#copy_save_done', fn: cancelOverlays, evt: 'click'},
+ {key: 'ctrl+left', fn () { rotateSelected(0, 1); }},
+ {key: 'ctrl+right', fn () { rotateSelected(1, 1); }},
+ {key: 'ctrl+shift+left', fn () { rotateSelected(0, 5); }},
+ {key: 'ctrl+shift+right', fn () { rotateSelected(1, 5); }},
+ {key: 'shift+O', fn: selectPrev},
+ {key: 'shift+P', fn: selectNext},
+ {key: [modKey + 'up', true], fn () { zoomImage(2); }},
+ {key: [modKey + 'down', true], fn () { zoomImage(0.5); }},
+ {key: [modKey + ']', true], fn () { moveUpDownSelected('Up'); }},
+ {key: [modKey + '[', true], fn () { moveUpDownSelected('Down'); }},
+ {key: ['up', true], fn () { moveSelected(0, -1); }},
+ {key: ['down', true], fn () { moveSelected(0, 1); }},
+ {key: ['left', true], fn () { moveSelected(-1, 0); }},
+ {key: ['right', true], fn () { moveSelected(1, 0); }},
+ {key: 'shift+up', fn () { moveSelected(0, -10); }},
+ {key: 'shift+down', fn () { moveSelected(0, 10); }},
+ {key: 'shift+left', fn () { moveSelected(-10, 0); }},
+ {key: 'shift+right', fn () { moveSelected(10, 0); }},
+ {key: ['alt+up', true], fn () { svgCanvas.cloneSelectedElements(0, -1); }},
+ {key: ['alt+down', true], fn () { svgCanvas.cloneSelectedElements(0, 1); }},
+ {key: ['alt+left', true], fn () { svgCanvas.cloneSelectedElements(-1, 0); }},
+ {key: ['alt+right', true], fn () { svgCanvas.cloneSelectedElements(1, 0); }},
+ {key: ['alt+shift+up', true], fn () { svgCanvas.cloneSelectedElements(0, -10); }},
+ {key: ['alt+shift+down', true], fn () { svgCanvas.cloneSelectedElements(0, 10); }},
+ {key: ['alt+shift+left', true], fn () { svgCanvas.cloneSelectedElements(-10, 0); }},
+ {key: ['alt+shift+right', true], fn () { svgCanvas.cloneSelectedElements(10, 0); }},
+ {key: 'A', fn () { svgCanvas.selectAllInCurrentLayer(); }},
- // Shortcuts not associated with buttons
+ // Standard shortcuts
+ {key: modKey + 'z', fn: clickUndo},
+ {key: modKey + 'shift+z', fn: clickRedo},
+ {key: modKey + 'y', fn: clickRedo},
- {key: 'ctrl+left', fn: function () { rotateSelected(0, 1); }},
- {key: 'ctrl+right', fn: function () { rotateSelected(1, 1); }},
- {key: 'ctrl+shift+left', fn: function () { rotateSelected(0, 5); }},
- {key: 'ctrl+shift+right', fn: function () { rotateSelected(1, 5); }},
- {key: 'shift+O', fn: selectPrev},
- {key: 'shift+P', fn: selectNext},
- {key: [modKey + 'up', true], fn: function () { zoomImage(2); }},
- {key: [modKey + 'down', true], fn: function () { zoomImage(0.5); }},
- {key: [modKey + ']', true], fn: function () { moveUpDownSelected('Up'); }},
- {key: [modKey + '[', true], fn: function () { moveUpDownSelected('Down'); }},
- {key: ['up', true], fn: function () { moveSelected(0, -1); }},
- {key: ['down', true], fn: function () { moveSelected(0, 1); }},
- {key: ['left', true], fn: function () { moveSelected(-1, 0); }},
- {key: ['right', true], fn: function () { moveSelected(1, 0); }},
- {key: 'shift+up', fn: function () { moveSelected(0, -10); }},
- {key: 'shift+down', fn: function () { moveSelected(0, 10); }},
- {key: 'shift+left', fn: function () { moveSelected(-10, 0); }},
- {key: 'shift+right', fn: function () { moveSelected(10, 0); }},
- {key: ['alt+up', true], fn: function () { svgCanvas.cloneSelectedElements(0, -1); }},
- {key: ['alt+down', true], fn: function () { svgCanvas.cloneSelectedElements(0, 1); }},
- {key: ['alt+left', true], fn: function () { svgCanvas.cloneSelectedElements(-1, 0); }},
- {key: ['alt+right', true], fn: function () { svgCanvas.cloneSelectedElements(1, 0); }},
- {key: ['alt+shift+up', true], fn: function () { svgCanvas.cloneSelectedElements(0, -10); }},
- {key: ['alt+shift+down', true], fn: function () { svgCanvas.cloneSelectedElements(0, 10); }},
- {key: ['alt+shift+left', true], fn: function () { svgCanvas.cloneSelectedElements(-10, 0); }},
- {key: ['alt+shift+right', true], fn: function () { svgCanvas.cloneSelectedElements(10, 0); }},
- {key: 'A', fn: function () { svgCanvas.selectAllInCurrentLayer(); }},
+ {key: modKey + 'x', fn: cutSelected},
+ {key: modKey + 'c', fn: copySelected},
+ {key: modKey + 'v', fn: pasteInCenter}
+ ];
- // Standard shortcuts
- {key: modKey + 'z', fn: clickUndo},
- {key: modKey + 'shift+z', fn: clickRedo},
- {key: modKey + 'y', fn: clickRedo},
-
- {key: modKey + 'x', fn: cutSelected},
- {key: modKey + 'c', fn: copySelected},
- {key: modKey + 'v', fn: pasteInCenter}
- ];
-
- // Tooltips not directly associated with a single function
- var keyAssocs = {
- '4/Shift+4': '#tools_rect_show',
- '5/Shift+5': '#tools_ellipse_show'
- };
-
- return {
- setAll: function () {
- var flyouts = {};
-
- $.each(toolButtons, function (i, opts) {
- // Bind function to button
- var btn;
- if (opts.sel) {
- btn = $(opts.sel);
- if (btn.length === 0) { return true; } // Skip if markup does not exist
- if (opts.evt) {
- if (svgedit.browser.isTouch() && opts.evt === 'click') {
- opts.evt = 'mousedown';
- }
- btn[opts.evt](opts.fn);
- }
-
- // Add to parent flyout menu, if able to be displayed
- if (opts.parent && $(opts.parent + '_show').length !== 0) {
- var fH = $(opts.parent);
- if (!fH.length) {
- fH = makeFlyoutHolder(opts.parent.substr(1));
- }
-
- fH.append(btn);
-
- if (!$.isArray(flyouts[opts.parent])) {
- flyouts[opts.parent] = [];
- }
- flyouts[opts.parent].push(opts);
- }
- }
-
- // Bind function to shortcut key
- if (opts.key) {
- // Set shortcut based on options
- var keyval,
- // disInInp = true,
- fn = opts.fn,
- pd = false;
- if ($.isArray(opts.key)) {
- keyval = opts.key[0];
- if (opts.key.length > 1) { pd = opts.key[1]; }
- // if (opts.key.length > 2) { disInInp = opts.key[2]; }
- } else {
- keyval = opts.key;
- }
- keyval += '';
-
- $.each(keyval.split('/'), function (i, key) {
- $(document).bind('keydown', key, function (e) {
- fn();
- if (pd) {
- e.preventDefault();
- }
- // Prevent default on ALL keys?
- return false;
- });
- });
-
- // Put shortcut in title
- if (opts.sel && !opts.hidekey && btn.attr('title')) {
- var newTitle = btn.attr('title').split('[')[0] + ' (' + keyval + ')';
- keyAssocs[keyval] = opts.sel;
- // Disregard for menu items
- if (!btn.parents('#main_menu').length) {
- btn.attr('title', newTitle);
- }
- }
- }
- });
-
- // Setup flyouts
- setupFlyouts(flyouts);
-
- // Misc additional actions
-
- // Make 'return' keypress trigger the change event
- $('.attr_changer, #image_url').bind('keydown', 'return',
- function (evt) {
- $(this).change();
- evt.preventDefault();
- }
- );
-
- $(window).bind('keydown', 'tab', function (e) {
- if (uiContext === 'canvas') {
- e.preventDefault();
- selectNext();
- }
- }).bind('keydown', 'shift+tab', function (e) {
- if (uiContext === 'canvas') {
- e.preventDefault();
- selectPrev();
- }
- });
-
- $('#tool_zoom').dblclick(dblclickZoom);
- },
- setTitles: function () {
- $.each(keyAssocs, function (keyval, sel) {
- var menu = ($(sel).parents('#main_menu').length);
-
- $(sel).each(function () {
- var t;
- if (menu) {
- t = $(this).text().split(' [')[0];
- } else {
- t = this.title.split(' [')[0];
- }
- var keyStr = '';
- // Shift+Up
- $.each(keyval.split('/'), function (i, key) {
- var modBits = key.split('+'), mod = '';
- if (modBits.length > 1) {
- mod = modBits[0] + '+';
- key = modBits[1];
- }
- keyStr += (i ? '/' : '') + mod + (uiStrings['key_' + key] || key);
- });
- if (menu) {
- this.lastChild.textContent = t + ' [' + keyStr + ']';
- } else {
- this.title = t + ' [' + keyStr + ']';
- }
- });
- });
- },
- getButtonData: function (sel) {
- var b;
- $.each(toolButtons, function (i, btn) {
- if (btn.sel === sel) { b = btn; }
- });
- return b;
- }
- };
- }());
-
- Actions.setAll();
-
- // Select given tool
- editor.ready(function () {
- var tool,
- itool = curConfig.initTool,
- container = $('#tools_left, #svg_editor .tools_flyout'),
- preTool = container.find('#tool_' + itool),
- regTool = container.find('#' + itool);
- if (preTool.length) {
- tool = preTool;
- } else if (regTool.length) {
- tool = regTool;
- } else {
- tool = $('#tool_select');
- }
- tool.click().mouseup();
-
- if (curConfig.wireframe) {
- $('#tool_wireframe').click();
- }
-
- if (curConfig.showlayers) {
- toggleSidePanel();
- }
-
- $('#rulers').toggle(!!curConfig.showRulers);
-
- if (curConfig.showRulers) {
- $('#show_rulers')[0].checked = true;
- }
-
- if (curConfig.baseUnit) {
- $('#base_unit').val(curConfig.baseUnit);
- }
-
- if (curConfig.gridSnapping) {
- $('#grid_snapping_on')[0].checked = true;
- }
-
- if (curConfig.snappingStep) {
- $('#grid_snapping_step').val(curConfig.snappingStep);
- }
-
- if (curConfig.gridColor) {
- $('#grid_color').val(curConfig.gridColor);
- }
- });
-
- // init SpinButtons
- $('#rect_rx').SpinButton({min: 0, max: 1000, callback: changeRectRadius});
- $('#stroke_width').SpinButton({min: 0, max: 99, smallStep: 0.1, callback: changeStrokeWidth});
- $('#angle').SpinButton({min: -180, max: 180, step: 5, callback: changeRotationAngle});
- $('#font_size').SpinButton({min: 0.001, stepfunc: stepFontSize, callback: changeFontSize});
- $('#group_opacity').SpinButton({min: 0, max: 100, step: 5, callback: changeOpacity});
- $('#blur').SpinButton({min: 0, max: 10, step: 0.1, callback: changeBlur});
- $('#zoom').SpinButton({min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, callback: changeZoom})
- // Set default zoom
- .val(svgCanvas.getZoom() * 100);
-
- $('#workarea').contextMenu(
- {
- menu: 'cmenu_canvas',
- inSpeed: 0
- },
- function (action, el, pos) {
- switch (action) {
- case 'delete':
- deleteSelected();
- break;
- case 'cut':
- cutSelected();
- break;
- case 'copy':
- copySelected();
- break;
- case 'paste':
- svgCanvas.pasteElements();
- break;
- case 'paste_in_place':
- svgCanvas.pasteElements('in_place');
- break;
- case 'group':
- case 'group_elements':
- svgCanvas.groupSelectedElements();
- break;
- case 'ungroup':
- svgCanvas.ungroupSelectedElement();
- break;
- case 'move_front':
- moveToTopSelected();
- break;
- case 'move_up':
- moveUpDownSelected('Up');
- break;
- case 'move_down':
- moveUpDownSelected('Down');
- break;
- case 'move_back':
- moveToBottomSelected();
- break;
- default:
- if (svgedit.contextmenu && svgedit.contextmenu.hasCustomHandler(action)) {
- svgedit.contextmenu.getCustomHandler(action).call();
- }
- break;
- }
- }
- );
-
- var lmenuFunc = function (action, el, pos) {
- switch (action) {
- case 'dupe':
- cloneLayer();
- break;
- case 'delete':
- deleteLayer();
- break;
- case 'merge_down':
- mergeLayer();
- break;
- case 'merge_all':
- svgCanvas.mergeAllLayers();
- updateContextPanel();
- populateLayers();
- break;
- }
+ // Tooltips not directly associated with a single function
+ const keyAssocs = {
+ '4/Shift+4': '#tools_rect_show',
+ '5/Shift+5': '#tools_ellipse_show'
};
- $('#layerlist').contextMenu(
- {
- menu: 'cmenu_layers',
- inSpeed: 0
+ return {
+ setAll () {
+ const flyouts = {};
+
+ $.each(toolButtons, function (i, opts) {
+ // Bind function to button
+ let btn;
+ if (opts.sel) {
+ btn = $(opts.sel);
+ if (!btn.length) { return true; } // Skip if markup does not exist
+ if (opts.evt) {
+ if (isTouch() && opts.evt === 'click') {
+ opts.evt = 'mousedown';
+ }
+ btn[opts.evt](opts.fn);
+ }
+
+ // Add to parent flyout menu, if able to be displayed
+ if (opts.parent && $(opts.parent + '_show').length) {
+ let fH = $(opts.parent);
+ if (!fH.length) {
+ fH = makeFlyoutHolder(opts.parent.substr(1));
+ }
+
+ fH.append(btn);
+
+ if (!Array.isArray(flyouts[opts.parent])) {
+ flyouts[opts.parent] = [];
+ }
+ flyouts[opts.parent].push(opts);
+ }
+ }
+
+ // Bind function to shortcut key
+ if (opts.key) {
+ // Set shortcut based on options
+ let keyval,
+ // disInInp = true,
+ pd = false;
+ if (Array.isArray(opts.key)) {
+ keyval = opts.key[0];
+ if (opts.key.length > 1) { pd = opts.key[1]; }
+ // if (opts.key.length > 2) { disInInp = opts.key[2]; }
+ } else {
+ keyval = opts.key;
+ }
+ keyval += '';
+
+ const {fn} = opts;
+ $.each(keyval.split('/'), function (i, key) {
+ $(document).bind('keydown', key, function (e) {
+ fn();
+ if (pd) {
+ e.preventDefault();
+ }
+ // Prevent default on ALL keys?
+ return false;
+ });
+ });
+
+ // Put shortcut in title
+ if (opts.sel && !opts.hidekey && btn.attr('title')) {
+ const newTitle = btn.attr('title').split('[')[0] + ' (' + keyval + ')';
+ keyAssocs[keyval] = opts.sel;
+ // Disregard for menu items
+ if (!btn.parents('#main_menu').length) {
+ btn.attr('title', newTitle);
+ }
+ }
+ }
+ });
+
+ // Setup flyouts
+ setupFlyouts(flyouts);
+
+ // Misc additional actions
+
+ // Make 'return' keypress trigger the change event
+ $('.attr_changer, #image_url').bind('keydown', 'return',
+ function (evt) {
+ $(this).change();
+ evt.preventDefault();
+ }
+ );
+
+ $(window).bind('keydown', 'tab', function (e) {
+ if (uiContext === 'canvas') {
+ e.preventDefault();
+ selectNext();
+ }
+ }).bind('keydown', 'shift+tab', function (e) {
+ if (uiContext === 'canvas') {
+ e.preventDefault();
+ selectPrev();
+ }
+ });
+
+ $('#tool_zoom').dblclick(dblclickZoom);
},
- lmenuFunc
- );
+ setTitles () {
+ $.each(keyAssocs, function (keyval, sel) {
+ const menu = ($(sel).parents('#main_menu').length);
- $('#layer_moreopts').contextMenu(
- {
- menu: 'cmenu_layers',
- inSpeed: 0,
- allowLeft: true
+ $(sel).each(function () {
+ let t;
+ if (menu) {
+ t = $(this).text().split(' [')[0];
+ } else {
+ t = this.title.split(' [')[0];
+ }
+ let keyStr = '';
+ // Shift+Up
+ $.each(keyval.split('/'), function (i, key) {
+ const modBits = key.split('+');
+ let mod = '';
+ if (modBits.length > 1) {
+ mod = modBits[0] + '+';
+ key = modBits[1];
+ }
+ keyStr += (i ? '/' : '') + mod + (uiStrings['key_' + key] || key);
+ });
+ if (menu) {
+ this.lastChild.textContent = t + ' [' + keyStr + ']';
+ } else {
+ this.title = t + ' [' + keyStr + ']';
+ }
+ });
+ });
},
- lmenuFunc
- );
+ getButtonData (sel) {
+ let b;
+ $.each(toolButtons, function (i, btn) {
+ if (btn.sel === sel) { b = btn; }
+ });
+ return b;
+ }
+ };
+ }());
- $('.contextMenu li').mousedown(function (ev) {
- ev.preventDefault();
- });
+ Actions.setAll();
- $('#cmenu_canvas li').disableContextMenu();
- canvMenu.enableContextMenuItems('#delete,#cut,#copy');
+ // Select given tool
+ editor.ready(function () {
+ let tool;
+ const itool = curConfig.initTool,
+ container = $('#tools_left, #svg_editor .tools_flyout'),
+ preTool = container.find('#tool_' + itool),
+ regTool = container.find('#' + itool);
+ if (preTool.length) {
+ tool = preTool;
+ } else if (regTool.length) {
+ tool = regTool;
+ } else {
+ tool = $('#tool_select');
+ }
+ tool.click().mouseup();
+
+ if (curConfig.wireframe) {
+ $('#tool_wireframe').click();
+ }
+
+ if (curConfig.showlayers) {
+ toggleSidePanel();
+ }
+
+ $('#rulers').toggle(!!curConfig.showRulers);
+
+ if (curConfig.showRulers) {
+ $('#show_rulers')[0].checked = true;
+ }
+
+ if (curConfig.baseUnit) {
+ $('#base_unit').val(curConfig.baseUnit);
+ }
+
+ if (curConfig.gridSnapping) {
+ $('#grid_snapping_on')[0].checked = true;
+ }
+
+ if (curConfig.snappingStep) {
+ $('#grid_snapping_step').val(curConfig.snappingStep);
+ }
+
+ if (curConfig.gridColor) {
+ $('#grid_color').val(curConfig.gridColor);
+ }
+ });
+
+ // init SpinButtons
+ const stateObj = {tool_scale: editor.tool_scale};
+ $('#rect_rx').SpinButton({min: 0, max: 1000, stateObj, callback: changeRectRadius});
+ $('#stroke_width').SpinButton({min: 0, max: 99, smallStep: 0.1, stateObj, callback: changeStrokeWidth});
+ $('#angle').SpinButton({min: -180, max: 180, step: 5, stateObj, callback: changeRotationAngle});
+ $('#font_size').SpinButton({min: 0.001, stepfunc: stepFontSize, stateObj, callback: changeFontSize});
+ $('#group_opacity').SpinButton({min: 0, max: 100, step: 5, stateObj, callback: changeOpacity});
+ $('#blur').SpinButton({min: 0, max: 10, step: 0.1, stateObj, callback: changeBlur});
+ $('#zoom').SpinButton({min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, stateObj, callback: changeZoom})
+ // Set default zoom
+ .val(svgCanvas.getZoom() * 100);
+
+ $('#workarea').contextMenu(
+ {
+ menu: 'cmenu_canvas',
+ inSpeed: 0
+ },
+ function (action, el, pos) {
+ switch (action) {
+ case 'delete':
+ deleteSelected();
+ break;
+ case 'cut':
+ cutSelected();
+ break;
+ case 'copy':
+ copySelected();
+ break;
+ case 'paste':
+ svgCanvas.pasteElements();
+ break;
+ case 'paste_in_place':
+ svgCanvas.pasteElements('in_place');
+ break;
+ case 'group':
+ case 'group_elements':
+ svgCanvas.groupSelectedElements();
+ break;
+ case 'ungroup':
+ svgCanvas.ungroupSelectedElement();
+ break;
+ case 'move_front':
+ moveToTopSelected();
+ break;
+ case 'move_up':
+ moveUpDownSelected('Up');
+ break;
+ case 'move_down':
+ moveUpDownSelected('Down');
+ break;
+ case 'move_back':
+ moveToBottomSelected();
+ break;
+ default:
+ if (hasCustomHandler(action)) {
+ getCustomHandler(action).call();
+ }
+ break;
+ }
+ }
+ );
+
+ const lmenuFunc = function (action, el, pos) {
+ switch (action) {
+ case 'dupe':
+ cloneLayer();
+ break;
+ case 'delete':
+ deleteLayer();
+ break;
+ case 'merge_down':
+ mergeLayer();
+ break;
+ case 'merge_all':
+ svgCanvas.mergeAllLayers();
+ updateContextPanel();
+ populateLayers();
+ break;
+ }
+ };
+
+ $('#layerlist').contextMenu(
+ {
+ menu: 'cmenu_layers',
+ inSpeed: 0
+ },
+ lmenuFunc
+ );
+
+ $('#layer_moreopts').contextMenu(
+ {
+ menu: 'cmenu_layers',
+ inSpeed: 0,
+ allowLeft: true
+ },
+ lmenuFunc
+ );
+
+ $('.contextMenu li').mousedown(function (ev) {
+ ev.preventDefault();
+ });
+
+ $('#cmenu_canvas li').disableContextMenu();
+ canvMenu.enableContextMenuItems('#delete,#cut,#copy');
+
+ canvMenu[(localStorage.getItem('svgedit_clipboard') ? 'en' : 'dis') + 'ableContextMenuItems'](
+ '#paste,#paste_in_place'
+ );
+ window.addEventListener('storage', function (e) {
+ if (e.key !== 'svgedit_clipboard') return;
canvMenu[(localStorage.getItem('svgedit_clipboard') ? 'en' : 'dis') + 'ableContextMenuItems'](
'#paste,#paste_in_place'
);
- window.addEventListener('storage', function (e) {
- if (e.key !== 'svgedit_clipboard') return;
+ });
- canvMenu[(localStorage.getItem('svgedit_clipboard') ? 'en' : 'dis') + 'ableContextMenuItems'](
- '#paste,#paste_in_place'
- );
- });
+ window.addEventListener('beforeunload', function (e) {
+ // Suppress warning if page is empty
+ if (undoMgr.getUndoStackSize() === 0) {
+ editor.showSaveWarning = false;
+ }
- window.addEventListener('beforeunload', function (e) {
- // Suppress warning if page is empty
- if (undoMgr.getUndoStackSize() === 0) {
- editor.showSaveWarning = false;
- }
+ // showSaveWarning is set to 'false' when the page is saved.
+ if (!curConfig.no_save_warning && editor.showSaveWarning) {
+ // Browser already asks question about closing the page
+ e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
+ return uiStrings.notification.unsavedChanges;
+ }
+ }, false);
- // showSaveWarning is set to 'false' when the page is saved.
- if (!curConfig.no_save_warning && editor.showSaveWarning) {
- // Browser already asks question about closing the page
- e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
- return uiStrings.notification.unsavedChanges;
- }
- }, false);
+ editor.openPrep = function (func) {
+ $('#main_menu').hide();
+ if (undoMgr.getUndoStackSize() === 0) {
+ func(true);
+ } else {
+ $.confirm(uiStrings.notification.QwantToOpen, func);
+ }
+ };
- editor.openPrep = function (func) {
+ function onDragEnter (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ // and indicator should be displayed here, such as "drop files here"
+ }
+
+ function onDragOver (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+
+ function onDragLeave (e) {
+ e.stopPropagation();
+ e.preventDefault();
+ // hypothetical indicator should be removed here
+ }
+ // Use HTML5 File API: http://www.w3.org/TR/FileAPI/
+ // if browser has HTML5 File API support, then we will show the open menu item
+ // and provide a file input to click. When that change event fires, it will
+ // get the text contents of the file and send it to the canvas
+ if (window.FileReader) {
+ const importImage = function (e) {
+ $.process_cancel(uiStrings.notification.loadingImage);
+ e.stopPropagation();
+ e.preventDefault();
+ $('#workarea').removeAttr('style');
$('#main_menu').hide();
- if (undoMgr.getUndoStackSize() === 0) {
- func(true);
- } else {
- $.confirm(uiStrings.notification.QwantToOpen, func);
- }
- };
-
- function onDragEnter (e) {
- e.stopPropagation();
- e.preventDefault();
- // and indicator should be displayed here, such as "drop files here"
- }
-
- function onDragOver (e) {
- e.stopPropagation();
- e.preventDefault();
- }
-
- function onDragLeave (e) {
- e.stopPropagation();
- e.preventDefault();
- // hypothetical indicator should be removed here
- }
- // Use HTML5 File API: https://www.w3.org/TR/FileAPI/
- // if browser has HTML5 File API support, then we will show the open menu item
- // and provide a file input to click. When that change event fires, it will
- // get the text contents of the file and send it to the canvas
- if (window.FileReader) {
- var importImage = function (e) {
- $.process_cancel(uiStrings.notification.loadingImage);
- e.stopPropagation();
- e.preventDefault();
- $('#workarea').removeAttr('style');
- $('#main_menu').hide();
- var file = (e.type === 'drop') ? e.dataTransfer.files[0] : this.files[0];
- if (!file) {
- $('#dialog_box').hide();
- return;
- }
- /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports
-
- }
- else */
- if (file.type.indexOf('image') > -1) {
- // Detected an image
- // svg handling
- var reader;
- if (file.type.indexOf('svg') > -1) {
- reader = new FileReader();
- reader.onloadend = function (e) {
- var newElement = svgCanvas.importSvgString(e.target.result, true);
- svgCanvas.ungroupSelectedElement();
- svgCanvas.ungroupSelectedElement();
- svgCanvas.groupSelectedElements();
- svgCanvas.alignSelectedElements('m', 'page');
- svgCanvas.alignSelectedElements('c', 'page');
- // highlight imported element, otherwise we get strange empty selectbox
- svgCanvas.selectOnly([newElement]);
- $('#dialog_box').hide();
- };
- reader.readAsText(file);
- } else {
- // bitmap handling
- reader = new FileReader();
- reader.onloadend = function (e) {
- // let's insert the new image until we know its dimensions
- var insertNewImage = function (width, height) {
- var newImage = svgCanvas.addSvgElementFromJson({
- element: 'image',
- attr: {
- x: 0,
- y: 0,
- width: width,
- height: height,
- id: svgCanvas.getNextId(),
- style: 'pointer-events:inherit'
- }
- });
- svgCanvas.setHref(newImage, e.target.result);
- svgCanvas.selectOnly([newImage]);
- svgCanvas.alignSelectedElements('m', 'page');
- svgCanvas.alignSelectedElements('c', 'page');
- updateContextPanel();
- $('#dialog_box').hide();
- };
- // create dummy img so we know the default dimensions
- var imgWidth = 100;
- var imgHeight = 100;
- var img = new Image();
- img.src = e.target.result;
- img.style.opacity = 0;
- img.onload = function () {
- imgWidth = img.offsetWidth;
- imgHeight = img.offsetHeight;
- insertNewImage(imgWidth, imgHeight);
- };
- };
- reader.readAsDataURL(file);
- }
- }
- };
-
- workarea[0].addEventListener('dragenter', onDragEnter, false);
- workarea[0].addEventListener('dragover', onDragOver, false);
- workarea[0].addEventListener('dragleave', onDragLeave, false);
- workarea[0].addEventListener('drop', importImage, false);
-
- var open = $('
').change(function () {
- var f = this;
- editor.openPrep(function (ok) {
- if (!ok) { return; }
- svgCanvas.clear();
- if (f.files.length === 1) {
- $.process_cancel(uiStrings.notification.loadingImage);
- var reader = new FileReader();
- reader.onloadend = function (e) {
- loadSvgString(e.target.result);
- updateCanvas();
- };
- reader.readAsText(f.files[0]);
- }
- });
- });
- $('#tool_open').show().prepend(open);
-
- var imgImport = $('
').change(importImage);
- $('#tool_import').show().prepend(imgImport);
- }
-
- // $(function () {
- updateCanvas(true);
- // });
-
- // var revnums = "svg-editor.js ($Rev$) ";
- // revnums += svgCanvas.getVersion();
- // $('#copyright')[0].setAttribute('title', revnums);
-
- // For Compatibility with older extensions
- $(function () {
- window.svgCanvas = svgCanvas;
- svgCanvas.ready = editor.ready;
- });
-
- editor.setLang = function (lang, allStrings) {
- editor.langChanged = true;
- $.pref('lang', lang);
- $('#lang_select').val(lang);
- if (!allStrings) {
+ const file = (e.type === 'drop') ? e.dataTransfer.files[0] : this.files[0];
+ if (!file) {
+ $('#dialog_box').hide();
return;
}
- // var notif = allStrings.notification; // Currently unused
- // $.extend will only replace the given strings
- var oldLayerName = $('#layerlist tr.layersel td.layername').text();
- var renameLayer = (oldLayerName === uiStrings.common.layer + ' 1');
+ /* if (file.type === 'application/pdf') { // Todo: Handle PDF imports
- $.extend(uiStrings, allStrings);
- svgCanvas.setUiStrings(allStrings);
- Actions.setTitles();
-
- if (renameLayer) {
- svgCanvas.renameCurrentLayer(uiStrings.common.layer + ' 1');
- populateLayers();
}
-
- // In case extensions loaded before the locale, now we execute a callback on them
- if (extsPreLang.length) {
- while (extsPreLang.length) {
- var ext = extsPreLang.shift();
- ext.langReady({lang: lang, uiStrings: uiStrings});
+ else */
+ if (file.type.includes('image')) {
+ // Detected an image
+ // svg handling
+ let reader;
+ if (file.type.includes('svg')) {
+ reader = new FileReader();
+ reader.onloadend = function (e) {
+ const newElement = svgCanvas.importSvgString(e.target.result, true);
+ svgCanvas.ungroupSelectedElement();
+ svgCanvas.ungroupSelectedElement();
+ svgCanvas.groupSelectedElements();
+ svgCanvas.alignSelectedElements('m', 'page');
+ svgCanvas.alignSelectedElements('c', 'page');
+ // highlight imported element, otherwise we get strange empty selectbox
+ svgCanvas.selectOnly([newElement]);
+ $('#dialog_box').hide();
+ };
+ reader.readAsText(file);
+ } else {
+ // bitmap handling
+ reader = new FileReader();
+ reader.onloadend = function (e) {
+ // let's insert the new image until we know its dimensions
+ const insertNewImage = function (width, height) {
+ const newImage = svgCanvas.addSvgElementFromJson({
+ element: 'image',
+ attr: {
+ x: 0,
+ y: 0,
+ width,
+ height,
+ id: svgCanvas.getNextId(),
+ style: 'pointer-events:inherit'
+ }
+ });
+ svgCanvas.setHref(newImage, e.target.result);
+ svgCanvas.selectOnly([newImage]);
+ svgCanvas.alignSelectedElements('m', 'page');
+ svgCanvas.alignSelectedElements('c', 'page');
+ updateContextPanel();
+ $('#dialog_box').hide();
+ };
+ // create dummy img so we know the default dimensions
+ let imgWidth = 100;
+ let imgHeight = 100;
+ const img = new Image();
+ img.src = e.target.result;
+ img.style.opacity = 0;
+ img.onload = function () {
+ imgWidth = img.offsetWidth;
+ imgHeight = img.offsetHeight;
+ insertNewImage(imgWidth, imgHeight);
+ };
+ };
+ reader.readAsDataURL(file);
}
- } else {
- svgCanvas.runExtensions('langReady', {lang: lang, uiStrings: uiStrings});
}
- svgCanvas.runExtensions('langChanged', lang);
-
- // Update flyout tooltips
- setFlyoutTitles();
-
- // Copy title for certain tool elements
- var elems = {
- '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block',
- '#fill_color': '#tool_fill label, #tool_fill .color_block',
- '#linejoin_miter': '#cur_linejoin',
- '#linecap_butt': '#cur_linecap'
- };
-
- $.each(elems, function (source, dest) {
- $(dest).attr('title', $(source)[0].title);
- });
-
- // Copy alignment titles
- $('#multiselected_panel div[id^=tool_align]').each(function () {
- $('#tool_pos' + this.id.substr(10))[0].title = this.title;
- });
};
- };
- editor.ready = function (cb) {
- if (!isReady) {
- callbacks.push(cb);
- } else {
- cb();
- }
- };
+ workarea[0].addEventListener('dragenter', onDragEnter, false);
+ workarea[0].addEventListener('dragover', onDragOver, false);
+ workarea[0].addEventListener('dragleave', onDragLeave, false);
+ workarea[0].addEventListener('drop', importImage, false);
- editor.runCallbacks = function () {
- $.each(callbacks, function () {
- this();
- });
- isReady = true;
- };
-
- editor.loadFromString = function (str) {
- editor.ready(function () {
- loadSvgString(str);
- });
- };
-
- editor.disableUI = function (featList) {
- // $(function () {
- // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();
- // $('#tools_top').css('left', 5);
- // });
- };
-
- editor.loadFromURL = function (url, opts) {
- if (!opts) { opts = {}; }
-
- var cache = opts.cache;
- var cb = opts.callback;
-
- editor.ready(function () {
- $.ajax({
- 'url': url,
- 'dataType': 'text',
- cache: !!cache,
- beforeSend: function () {
+ const open = $('
').change(function () {
+ const f = this;
+ editor.openPrep(function (ok) {
+ if (!ok) { return; }
+ svgCanvas.clear();
+ if (f.files.length === 1) {
$.process_cancel(uiStrings.notification.loadingImage);
- },
- success: function (str) {
- loadSvgString(str, cb);
- },
- error: function (xhr, stat, err) {
- if (xhr.status !== 404 && xhr.responseText) {
- loadSvgString(xhr.responseText, cb);
- } else {
- $.alert(uiStrings.notification.URLloadFail + ': \n' + err, cb);
- }
- },
- complete: function () {
- $('#dialog_box').hide();
+ const reader = new FileReader();
+ reader.onloadend = function (e) {
+ loadSvgString(e.target.result);
+ updateCanvas();
+ };
+ reader.readAsText(f.files[0]);
}
});
});
- };
+ $('#tool_open').show().prepend(open);
- editor.loadFromDataURI = function (str) {
- editor.ready(function () {
- var base64 = false;
- var pre = str.match(/^data:image\/svg\+xml;base64,/);
- if (pre) {
- base64 = true;
- } else {
- pre = str.match(/^data:image\/svg\+xml(?:;(?:utf8)?)?,/);
+ const imgImport = $('
').change(importImage);
+ $('#tool_import').show().prepend(imgImport);
+ }
+
+ // $(function () {
+ updateCanvas(true);
+ // });
+
+ // const revnums = "svg-editor.js ($Rev$) ";
+ // revnums += svgCanvas.getVersion();
+ // $('#copyright')[0].setAttribute('title', revnums);
+
+ // For Compatibility with older extensions
+ $(function () {
+ window.svgCanvas = svgCanvas;
+ svgCanvas.ready = editor.ready;
+ });
+
+ const setLang = editor.setLang = function (lang, allStrings) {
+ editor.langChanged = true;
+ $.pref('lang', lang);
+ $('#lang_select').val(lang);
+ if (!allStrings) {
+ return;
+ }
+ // const notif = allStrings.notification; // Currently unused
+ // $.extend will only replace the given strings
+ const oldLayerName = $('#layerlist tr.layersel td.layername').text();
+ const renameLayer = (oldLayerName === uiStrings.common.layer + ' 1');
+
+ $.extend(uiStrings, allStrings);
+ svgCanvas.setUiStrings(allStrings);
+ Actions.setTitles();
+
+ if (renameLayer) {
+ svgCanvas.renameCurrentLayer(uiStrings.common.layer + ' 1');
+ populateLayers();
+ }
+
+ // In case extensions loaded before the locale, now we execute a callback on them
+ if (extsPreLang.length) {
+ while (extsPreLang.length) {
+ const ext = extsPreLang.shift();
+ ext.langReady({lang, uiStrings});
}
- if (pre) {
- pre = pre[0];
- }
- var src = str.slice(pre.length);
- loadSvgString(base64 ? Utils.decode64(src) : decodeURIComponent(src));
+ } else {
+ svgCanvas.runExtensions('langReady', {lang, uiStrings});
+ }
+ svgCanvas.runExtensions('langChanged', lang);
+
+ // Update flyout tooltips
+ setFlyoutTitles();
+
+ // Copy title for certain tool elements
+ const elems = {
+ '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block',
+ '#fill_color': '#tool_fill label, #tool_fill .color_block',
+ '#linejoin_miter': '#cur_linejoin',
+ '#linecap_butt': '#cur_linecap'
+ };
+
+ $.each(elems, function (source, dest) {
+ $(dest).attr('title', $(source)[0].title);
+ });
+
+ // Copy alignment titles
+ $('#multiselected_panel div[id^=tool_align]').each(function () {
+ $('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
};
+ localeInit({
+ addLangData (langParam) {
+ editor.canvas.runExtensions('addlangData', langParam, true);
+ },
+ curConfig,
+ setLang
+ });
+};
- editor.addExtension = function () {
- var args = arguments;
+editor.ready = function (cb) {
+ if (!isReady) {
+ callbacks.push(cb);
+ } else {
+ cb();
+ }
+};
- // Note that we don't want this on editor.ready since some extensions
- // may want to run before then (like server_opensave).
- $(function () {
- if (svgCanvas) { svgCanvas.addExtension.apply(this, args); }
+editor.runCallbacks = function () {
+ $.each(callbacks, function () {
+ this();
+ });
+ isReady = true;
+};
+
+editor.loadFromString = function (str) {
+ editor.ready(function () {
+ loadSvgString(str);
+ });
+};
+
+editor.disableUI = function (featList) {
+ // $(function () {
+ // $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();
+ // $('#tools_top').css('left', 5);
+ // });
+};
+
+editor.loadFromURL = function (url, opts) {
+ if (!opts) { opts = {}; }
+
+ const {cache, callback: cb} = opts;
+
+ editor.ready(function () {
+ $.ajax({
+ url,
+ dataType: 'text',
+ cache: !!cache,
+ beforeSend () {
+ $.process_cancel(uiStrings.notification.loadingImage);
+ },
+ success (str) {
+ loadSvgString(str, cb);
+ },
+ error (xhr, stat, err) {
+ if (xhr.status !== 404 && xhr.responseText) {
+ loadSvgString(xhr.responseText, cb);
+ } else {
+ $.alert(uiStrings.notification.URLloadFail + ': \n' + err, cb);
+ }
+ },
+ complete () {
+ $('#dialog_box').hide();
+ }
});
- };
+ });
+};
- return editor;
-}(jQuery));
+editor.loadFromDataURI = function (str) {
+ editor.ready(function () {
+ let base64 = false;
+ let pre = str.match(/^data:image\/svg\+xml;base64,/);
+ if (pre) {
+ base64 = true;
+ } else {
+ pre = str.match(/^data:image\/svg\+xml(?:;(?:utf8)?)?,/);
+ }
+ if (pre) {
+ pre = pre[0];
+ }
+ const src = str.slice(pre.length);
+ loadSvgString(base64 ? Utils.decode64(src) : decodeURIComponent(src));
+ });
+};
+
+editor.addExtension = function () {
+ const args = arguments;
+
+ // Note that we don't want this on editor.ready since some extensions
+ // may want to run before then (like server_opensave).
+ $(function () {
+ if (svgCanvas) { svgCanvas.addExtension.apply(this, args); }
+ });
+};
+
+// Defer injection to wait out initial menu processing. This probably goes
+// away once all context menu behavior is brought to context menu.
+editor.ready(() => {
+ injectExtendedContextMenuItemsIntoDom();
+});
// Run init once DOM is loaded
-$(svgEditor.init);
-}());
+jQuery(editor.init);
+
+export default editor;
diff --git a/editor/svg-editor.manifest b/editor/svg-editor.manifest
index 0f581465..2f3302c9 100644
--- a/editor/svg-editor.manifest
+++ b/editor/svg-editor.manifest
@@ -7,7 +7,7 @@ jgraduate/css/jPicker.css
jgraduate/css/jgraduate.css
svg-editor.css
spinbtn/JQuerySpinBtn.css
-jquery.js
+jquery.min.js
config.js
custom.css
js-hotkeys/jquery.hotkeys.min.js
diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js
index 895615ef..b40bd9ae 100644
--- a/editor/svgcanvas.js
+++ b/editor/svgcanvas.js
@@ -1,5 +1,5 @@
-/* eslint-disable no-var, indent, no-redeclare */
-/* globals $, svgedit, svgCanvas, jsPDF, canvg */
+/* eslint-disable indent */
+/* globals jQuery */
/*
* svgcanvas.js
*
@@ -13,22 +13,58 @@
// Dependencies:
// 1) jQuery
-// 2) pathseg.js
-// 3) browser.js
-// 4) svgtransformlist.js
-// 5) math.js
-// 6) units.js
-// 7) svgutils.js
-// 8) sanitize.js
-// 9) history.js
-// 10) historyrecording.js
-// 11) select.js
-// 12) draw.js
-// 13) path.js
-// 14) coords.js
-// 15) recalculate.js
-(function () {
+import './pathseg.js';
+import HistoryRecordingService from './historyrecording.js';
+import sanitizeSvg from './sanitize.js';
+import canvg from './canvg/canvg.js';
+
+import * as draw from './draw.js';
+import * as pathModule from './path.js';
+import {getReverseNS, NS} from './svgedit.js';
+import {
+ text2xml, assignAttributes, cleanupElement, getElem, getUrlFromAttr,
+ findDefs, getHref, setHref, getRefElem, getRotationAngle, getPathBBox,
+ preventClickDefault, snapToGrid, walkTree, walkTreePost,
+ getBBoxOfElementAsPath, convertToPath, toXml, encode64,
+ buildJSPDFCallback, dataURLToObjectURL, createObjectURL,
+ buildCanvgCallback, convertPath,
+ init as utilsInit, getBBox as utilsGetBBox, getStrokedBBox as utilsGetStrokedBBox
+} from './svgutils.js';
+import * as history from './history.js';
+import {
+ transformPoint, matrixMultiply, hasMatrixTransform, transformListToTransform,
+ getMatrix, snapToAngle, isIdentity, rectsIntersect, transformBox
+} from './math.js';
+import {
+ convertToNum, convertAttrs, convertUnit, shortFloat, init as unitsInit
+} from './units.js'; // , getTypeMap
+import {
+ isGecko, isIE, isWebkit, supportsNonScalingStroke, supportsGoodTextCharPos
+} from './browser.js'; // , supportsEditableText
+import {
+ getTransformList, resetListMap,
+ SVGTransformList as SVGEditTransformList
+} from './svgtransformlist.js';
+import {
+ remapElement,
+ init as coordsInit
+} from './coords.js';
+import {
+ recalculateDimensions,
+ init as recalculateInit
+} from './recalculate.js';
+import {
+ getSelectorManager,
+ init as selectInit
+} from './select.js';
+
+const $ = jQuery;
+const {
+ MoveElementCommand, InsertElementCommand, RemoveElementCommand,
+ ChangeElementCommand, BatchCommand, UndoManager, HistoryEventTypes
+} = history;
+
if (!window.console) {
window.console = {};
window.console.log = function (str) {};
@@ -39,7 +75,6 @@ if (window.opera) {
window.console.log = function (str) { opera.postError(str); };
window.console.dir = function (str) {};
}
-}());
// Class: SvgCanvas
// The main SvgCanvas class that manages all SVG-related functions
@@ -48,12 +83,11 @@ if (window.opera) {
// container - The container HTML element that should hold the SVG root element
// config - An object that contains configuration data
-$.SvgCanvas = function (container, config) {
+export default function (container, config) {
// Alias Namespace constants
-var NS = svgedit.NS;
// Default configuration options
-var curConfig = {
+const curConfig = {
show_outside_canvas: true,
selectNew: true,
dimensions: [640, 480]
@@ -65,17 +99,17 @@ if (config) {
}
// Array with width/height of canvas
-var dimensions = curConfig.dimensions;
+const {dimensions} = curConfig;
-var canvas = this;
+const canvas = this;
// "document" element associated with the container (same as window.document using default svg-editor.js)
-// NOTE: This is not actually a SVG document, but a HTML document.
-var svgdoc = container.ownerDocument;
+// NOTE: This is not actually a SVG document, but an HTML document.
+const svgdoc = container.ownerDocument;
// This is a container for the document being edited, not the document itself.
-var svgroot = svgdoc.importNode(
- svgedit.utilities.text2xml(
+const svgroot = svgdoc.importNode(
+ text2xml(
'
-
-
-
diff --git a/screencasts/svgopen2010/script.js b/screencasts/svgopen2010/script.js
index 68ac2d1e..e6927955 100644
--- a/screencasts/svgopen2010/script.js
+++ b/screencasts/svgopen2010/script.js
@@ -1,101 +1,46 @@
-/* eslint-disable no-var */
-(function () {
-var doc = document;
-var disableBuilds = true;
+(() => {
+const doc = document;
+const disableBuilds = true;
-var ctr = 0;
-var spaces = /\s+/, a1 = [''];
+let ctr = 0;
-var toArray = function (list) {
- return Array.prototype.slice.call(list || [], 0);
-};
-
-var byId = function (id) {
+const byId = function (id) {
if (typeof id === 'string') { return doc.getElementById(id); }
return id;
};
-var query = function (query, root) {
+const query = function (query, root) {
if (!query) { return []; }
- if (typeof query !== 'string') { return toArray(query); }
+ if (typeof query !== 'string') { return [...query]; }
if (typeof root === 'string') {
root = byId(root);
if (!root) { return []; }
}
root = root || document;
- var rootIsDoc = (root.nodeType === 9);
- var doc = rootIsDoc ? root : (root.ownerDocument || document);
+ const rootIsDoc = (root.nodeType === 9);
+ const doc = rootIsDoc ? root : (root.ownerDocument || document);
// rewrite the query to be ID rooted
- if (!rootIsDoc || ('>~+'.indexOf(query.charAt(0)) >= 0)) {
+ if (!rootIsDoc || ('>~+'.includes(query[0]))) {
root.id = root.id || ('qUnique' + (ctr++));
query = '#' + root.id + ' ' + query;
}
// don't choke on something like ".yada.yada >"
- if ('>~+'.indexOf(query.slice(-1)) >= 0) { query += ' *'; }
+ if ('>~+'.includes(query.slice(-1))) { query += ' *'; }
- return toArray(doc.querySelectorAll(query));
+ return [...doc.querySelectorAll(query)];
};
-var strToArray = function (s) {
- if (typeof s === 'string' || s instanceof String) {
- if (s.indexOf(' ') < 0) {
- a1[0] = s;
- return a1;
- }
- return s.split(spaces);
- }
- return s;
-};
+const ua = navigator.userAgent;
+const isFF = parseFloat(ua.split('Firefox/')[1]) || undefined;
+const isWK = parseFloat(ua.split('WebKit/')[1]) || undefined;
+const isOpera = parseFloat(ua.split('Opera/')[1]) || undefined;
-var addClass = function (node, classStr) {
- classStr = strToArray(classStr);
- var cls = ' ' + node.className + ' ';
- for (var i = 0, len = classStr.length, c; i < len; ++i) {
- c = classStr[i];
- if (c && cls.indexOf(' ' + c + ' ') < 0) {
- cls += c + ' ';
- }
- }
- node.className = cls.trim();
-};
-
-var removeClass = function (node, classStr) {
- var cls;
- if (classStr !== undefined) {
- classStr = strToArray(classStr);
- cls = ' ' + node.className + ' ';
- for (var i = 0, len = classStr.length; i < len; ++i) {
- cls = cls.replace(' ' + classStr[i] + ' ', ' ');
- }
- cls = cls.trim();
- } else {
- cls = '';
- }
- if (node.className !== cls) {
- node.className = cls;
- }
-};
-
-var toggleClass = function (node, classStr) {
- var cls = ' ' + node.className + ' ';
- if (cls.indexOf(' ' + classStr.trim() + ' ') >= 0) {
- removeClass(node, classStr);
- } else {
- addClass(node, classStr);
- }
-};
-
-var ua = navigator.userAgent;
-var isFF = parseFloat(ua.split('Firefox/')[1]) || undefined;
-var isWK = parseFloat(ua.split('WebKit/')[1]) || undefined;
-var isOpera = parseFloat(ua.split('Opera/')[1]) || undefined;
-
-var canTransition = (function () {
- var ver = parseFloat(ua.split('Version/')[1]) || undefined;
+const canTransition = (function () {
+ const ver = parseFloat(ua.split('Version/')[1]) || undefined;
// test to determine if this browser can handle CSS transitions.
- var cachedCanTransition =
+ const cachedCanTransition =
(isWK || (isFF && isFF > 3.6) || (isOpera && ver >= 10.5));
return function () { return cachedCanTransition; };
})();
@@ -103,13 +48,13 @@ var canTransition = (function () {
//
// Slide class
//
-var Slide = function (node, idx) {
+const Slide = function (node, idx) {
this._node = node;
if (idx >= 0) {
this._count = idx + 1;
}
if (this._node) {
- addClass(this._node, 'slide distant-slide');
+ this._node.classList.add('slide', 'distant-slide');
}
this._makeCounter();
this._makeBuildList();
@@ -124,7 +69,7 @@ Slide.prototype = {
_states: [ 'distant-slide', 'far-past',
'past', 'current', 'future',
'far-future', 'distant-slide' ],
- setState: function (state) {
+ setState (state) {
if (typeof state !== 'string') {
state = this._states[state];
}
@@ -132,40 +77,40 @@ Slide.prototype = {
this._visited = true;
this._makeBuildList();
}
- removeClass(this._node, this._states);
- addClass(this._node, state);
+ this._node.classList.remove(...this._states);
+ this._node.classList.add(state);
this._currentState = state;
// delay first auto run. Really wish this were in CSS.
/*
this._runAutos();
*/
- var _t = this;
+ const _t = this;
setTimeout(function () { _t._runAutos(); }, 400);
},
- _makeCounter: function () {
+ _makeCounter () {
if (!this._count || !this._node) { return; }
- var c = doc.createElement('span');
+ const c = doc.createElement('span');
c.innerHTML = this._count;
c.className = 'counter';
this._node.appendChild(c);
},
- _makeBuildList: function () {
+ _makeBuildList () {
this._buildList = [];
if (disableBuilds) { return; }
if (this._node) {
this._buildList = query('[data-build] > *', this._node);
}
this._buildList.forEach(function (el) {
- addClass(el, 'to-build');
+ el.classList.add('to-build');
});
},
- _runAutos: function () {
+ _runAutos () {
if (this._currentState !== 'current') {
return;
}
// find the next auto, slice it out of the list, and run it
- var idx = -1;
+ let idx = -1;
this._buildList.some(function (n, i) {
if (n.hasAttribute('data-auto')) {
idx = i;
@@ -174,29 +119,29 @@ Slide.prototype = {
return false;
});
if (idx >= 0) {
- var elem = this._buildList.splice(idx, 1)[0];
- var transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd');
- var _t = this;
+ const elem = this._buildList.splice(idx, 1)[0];
+ const transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd');
+ const _t = this;
if (canTransition()) {
- var l = function (evt) {
+ const l = function (evt) {
elem.parentNode.removeEventListener(transitionEnd, l, false);
_t._runAutos();
};
elem.parentNode.addEventListener(transitionEnd, l, false);
- removeClass(elem, 'to-build');
+ elem.classList.remove('to-build');
} else {
setTimeout(function () {
- removeClass(elem, 'to-build');
+ elem.classList.remove('to-build');
_t._runAutos();
}, 400);
}
}
},
- buildNext: function () {
+ buildNext () {
if (!this._buildList.length) {
return false;
}
- removeClass(this._buildList.shift(), 'to-build');
+ this._buildList.shift().classList.remove('to-build');
return true;
}
};
@@ -204,17 +149,17 @@ Slide.prototype = {
//
// SlideShow class
//
-var SlideShow = function (slides) {
+const SlideShow = function (slides) {
this._slides = (slides || []).map(function (el, idx) {
return new Slide(el, idx);
});
- var h = window.location.hash;
+ const h = window.location.hash;
try {
this.current = parseInt(h.split('#slide')[1], 10);
} catch (e) { /* squeltch */ }
this.current = isNaN(this.current) ? 1 : this.current;
- var _t = this;
+ const _t = this;
doc.addEventListener('keydown',
function (e) { _t.handleKeys(e); }, false);
doc.addEventListener('mousewheel',
@@ -232,7 +177,7 @@ var SlideShow = function (slides) {
SlideShow.prototype = {
_slides: [],
- _update: function (dontPush) {
+ _update (dontPush) {
document.querySelector('#presentation-counter').innerText = this.current;
if (history.pushState) {
if (!dontPush) {
@@ -241,7 +186,7 @@ SlideShow.prototype = {
} else {
window.location.hash = 'slide' + this.current;
}
- for (var x = this.current - 1; x < this.current + 7; x++) {
+ for (let x = this.current - 1; x < this.current + 7; x++) {
if (this._slides[x - 4]) {
this._slides[x - 4].setState(Math.max(0, x - this.current));
}
@@ -249,17 +194,17 @@ SlideShow.prototype = {
},
current: 0,
- next: function () {
+ next () {
if (!this._slides[this.current - 1].buildNext()) {
this.current = Math.min(this.current + 1, this._slides.length);
this._update();
}
},
- prev: function () {
+ prev () {
this.current = Math.max(this.current - 1, 1);
this._update();
},
- go: function (num) {
+ go (num) {
if (history.pushState && this.current !== num) {
history.replaceState(this.current, 'Slide ' + this.current, '#slide' + this.current);
}
@@ -268,17 +213,17 @@ SlideShow.prototype = {
},
_notesOn: false,
- showNotes: function () {
- var notesOn = this._notesOn = !this._notesOn;
+ showNotes () {
+ const notesOn = this._notesOn = !this._notesOn;
query('.notes').forEach(function (el) {
el.style.display = (notesOn) ? 'block' : 'none';
});
},
- switch3D: function () {
- toggleClass(document.body, 'three-d');
+ switch3D () {
+ document.body.classList.toggle('three-d');
},
- handleWheel: function (e) {
- var delta = 0;
+ handleWheel (e) {
+ let delta = 0;
if (e.wheelDelta) {
delta = e.wheelDelta / 120;
if (isOpera) {
@@ -296,7 +241,7 @@ SlideShow.prototype = {
this.next();
}
},
- handleKeys: function (e) {
+ handleKeys (e) {
if (/^(input|textarea)$/i.test(e.target.nodeName)) return;
switch (e.keyCode) {
@@ -312,12 +257,12 @@ SlideShow.prototype = {
}
},
_touchStartX: 0,
- handleTouchStart: function (e) {
+ handleTouchStart (e) {
this._touchStartX = e.touches[0].pageX;
},
- handleTouchEnd: function (e) {
- var delta = this._touchStartX - e.changedTouches[0].pageX;
- var SWIPE_SIZE = 150;
+ handleTouchEnd (e) {
+ const delta = this._touchStartX - e.changedTouches[0].pageX;
+ const SWIPE_SIZE = 150;
if (delta > SWIPE_SIZE) {
this.next();
} else if (delta < -SWIPE_SIZE) {
@@ -327,48 +272,48 @@ SlideShow.prototype = {
};
// Initialize
-var slideshow = new SlideShow(query('.slide')); // eslint-disable-line no-unused-vars
+const slideshow = new SlideShow(query('.slide')); // eslint-disable-line no-unused-vars
document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false);
document.querySelector('#toggle-size').addEventListener('click', toggleSize, false);
document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false);
document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false);
-var counters = document.querySelectorAll('.counter');
-var slides = document.querySelectorAll('.slide');
+const counters = document.querySelectorAll('.counter');
+const slides = document.querySelectorAll('.slide');
function toggleCounter () {
- toArray(counters).forEach(function (el) {
+ [...counters].forEach(function (el) {
el.style.display = (el.offsetHeight) ? 'none' : 'block';
});
}
function toggleSize () {
- toArray(slides).forEach(function (el) {
+ [...slides].forEach(function (el) {
if (!/reduced/.test(el.className)) {
- addClass(el, 'reduced');
+ el.classList.add('reduced');
} else {
- removeClass(el, 'reduced');
+ el.classList.remove('reduced');
}
});
}
function toggleTransitions () {
- toArray(slides).forEach(function (el) {
+ [...slides].forEach(function (el) {
if (!/no-transitions/.test(el.className)) {
- addClass(el, 'no-transitions');
+ el.classList.add('no-transitions');
} else {
- removeClass(el, 'no-transitions');
+ el.classList.remove('no-transitions');
}
});
}
function toggleGradients () {
- toArray(slides).forEach(function (el) {
+ [...slides].forEach(function (el) {
if (!/no-gradients/.test(el.className)) {
- addClass(el, 'no-gradients');
+ el.classList.add('no-gradients');
} else {
- removeClass(el, 'no-gradients');
+ el.classList.remove('no-gradients');
}
});
}
diff --git a/test/all_tests.js b/test/all_tests.js
index 42c7ecef..4cadd3c3 100644
--- a/test/all_tests.js
+++ b/test/all_tests.js
@@ -1,12 +1,8 @@
-/* eslint-disable no-var */
-var iframes = document.getElementsByTagName('iframe');
-for (var i = 0, len = iframes.length; i < len; ++i) {
- var f = iframes[i];
- (function (f) {
- f.addEventListener('load', function () {
- f.contentWindow.QUnit.done = function () {
- f.style.height = (f.contentDocument.body.scrollHeight + 20) + 'px';
- };
- });
- })(f);
-}
+const iframes = document.querySelectorAll('iframe');
+[...iframes].forEach((f) => {
+ f.addEventListener('load', () => {
+ f.contentWindow.QUnit.done = () => {
+ f.style.height = (f.contentDocument.body.scrollHeight + 20) + 'px';
+ };
+ });
+});
diff --git a/test/contextmenu_test.html b/test/contextmenu_test.html
index df0162b5..315d771c 100644
--- a/test/contextmenu_test.html
+++ b/test/contextmenu_test.html
@@ -5,16 +5,16 @@
Unit Tests for contextmenu.js
-
+
-
+
diff --git a/test/contextmenu_test.js b/test/contextmenu_test.js
index 10b0d876..dbe239d6 100644
--- a/test/contextmenu_test.js
+++ b/test/contextmenu_test.js
@@ -1,62 +1,60 @@
-/* eslint-disable no-var */
/* eslint-env qunit */
-/* globals svgedit, $, equals */
-$(function () {
- // log function
- QUnit.log = function (details) {
- if (window.console && window.console.log) {
- window.console.log(details.result + ' :: ' + details.message);
- }
- };
+/* globals svgedit, equals */
- function tearDown () {
- svgedit.contextmenu.resetCustomMenus();
+// log function
+QUnit.log = function (details) {
+ if (window.console && window.console.log) {
+ window.console.log(details.result + ' :: ' + details.message);
}
+};
- module('svgedit.contextmenu');
+function tearDown () {
+ svgedit.contextmenu.resetCustomMenus();
+}
- test('Test svgedit.contextmenu package', function () {
- expect(4);
+module('svgedit.contextmenu');
- ok(svgedit.contextmenu, 'contextmenu registered correctly');
- ok(svgedit.contextmenu.add, 'contextmenu.add registered correctly');
- ok(svgedit.contextmenu.hasCustomHandler, 'contextmenu hasCustomHandler registered correctly');
- ok(svgedit.contextmenu.getCustomHandler, 'contextmenu getCustomHandler registered correctly');
- });
+test('Test svgedit.contextmenu package', function () {
+ expect(4);
- test('Test svgedit.contextmenu does not add invalid menu item', function () {
- expect(3);
-
- svgedit.contextmenu.add({id: 'justanid'});
- ok(!svgedit.contextmenu.hasCustomHandler('justanid'), 'menu item with just an id is invalid');
-
- svgedit.contextmenu.add({id: 'idandlabel', label: 'anicelabel'});
- ok(!svgedit.contextmenu.hasCustomHandler('idandlabel'), 'menu item with just an id and label is invalid');
-
- svgedit.contextmenu.add({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'});
- ok(!svgedit.contextmenu.hasCustomHandler('idandlabel'), 'menu item with action that is not a function is invalid');
- });
-
- test('Test svgedit.contextmenu adds valid menu item', function () {
- expect(2);
-
- var validItem = {id: 'valid', label: 'anicelabel', action: function () { alert('testing'); }};
- svgedit.contextmenu.add(validItem);
-
- ok(svgedit.contextmenu.hasCustomHandler('valid'), 'Valid menu item is added.');
- equals(svgedit.contextmenu.getCustomHandler('valid'), validItem.action, 'Valid menu action is added.');
- tearDown();
- });
-
- test('Test svgedit.contextmenu rejects valid duplicate menu item id', function () {
- expect(1);
-
- var validItem1 = {id: 'valid', label: 'anicelabel', action: function () { alert('testing'); }};
- var validItem2 = {id: 'valid', label: 'anicelabel', action: function () { alert('testingtwice'); }};
- svgedit.contextmenu.add(validItem1);
- svgedit.contextmenu.add(validItem2);
-
- equals(svgedit.contextmenu.getCustomHandler('valid'), validItem1.action, 'duplicate menu item is rejected.');
- tearDown();
- });
+ ok(svgedit.contextmenu, 'contextmenu registered correctly');
+ ok(svgedit.addContextMenuItem, 'addContextMenuItem registered correctly');
+ ok(svgedit.contextmenu.hasCustomMenuItemHandler, 'contextmenu hasCustomHandler registered correctly');
+ ok(svgedit.contextmenu.getCustomMenuItemHandler, 'contextmenu getCustomHandler registered correctly');
+});
+
+test('Test svgedit.contextmenu does not add invalid menu item', function () {
+ expect(3);
+
+ svgedit.addContextMenuItem({id: 'justanid'});
+ ok(!svgedit.contextmenu.hasCustomMenuItemHandler('justanid'), 'menu item with just an id is invalid');
+
+ svgedit.addContextMenuItem({id: 'idandlabel', label: 'anicelabel'});
+ ok(!svgedit.contextmenu.hasCustomMenuItemHandler('idandlabel'), 'menu item with just an id and label is invalid');
+
+ svgedit.addContextMenuItem({id: 'idandlabel', label: 'anicelabel', action: 'notafunction'});
+ ok(!svgedit.contextmenu.hasCustomMenuItemHandler('idandlabel'), 'menu item with action that is not a function is invalid');
+});
+
+test('Test svgedit.contextmenu adds valid menu item', function () {
+ expect(2);
+
+ const validItem = {id: 'valid', label: 'anicelabel', action () { alert('testing'); }};
+ svgedit.addContextMenuItem(validItem);
+
+ ok(svgedit.contextmenu.hasCustomMenuItemHandler('valid'), 'Valid menu item is added.');
+ equals(svgedit.contextmenu.getCustomMenuItemHandler('valid'), validItem.action, 'Valid menu action is added.');
+ tearDown();
+});
+
+test('Test svgedit.contextmenu rejects valid duplicate menu item id', function () {
+ expect(1);
+
+ const validItem1 = {id: 'valid', label: 'anicelabel', action () { alert('testing'); }};
+ const validItem2 = {id: 'valid', label: 'anicelabel', action () { alert('testingtwice'); }};
+ svgedit.addContextMenuItem(validItem1);
+ svgedit.addContextMenuItem(validItem2);
+
+ equals(svgedit.contextmenu.getCustomMenuItemHandler('valid'), validItem1.action, 'duplicate menu item is rejected.');
+ tearDown();
});
diff --git a/test/coords_test.html b/test/coords_test.html
index f76ed015..34f13db4 100644
--- a/test/coords_test.html
+++ b/test/coords_test.html
@@ -5,7 +5,7 @@
Unit Tests for coords.js
-
+
@@ -16,7 +16,7 @@
-
+
diff --git a/test/coords_test.js b/test/coords_test.js
index 317df82f..4571b024 100644
--- a/test/coords_test.js
+++ b/test/coords_test.js
@@ -1,336 +1,334 @@
/* eslint-env qunit */
-/* globals $, svgedit, equals */
-/* eslint-disable no-var */
-$(function () {
- // log function
- QUnit.log = function (details) {
- if (window.console && window.console.log) {
- window.console.log(details.result + ' :: ' + details.message);
+/* globals svgedit, equals */
+
+// log function
+QUnit.log = function (details) {
+ if (window.console && window.console.log) {
+ window.console.log(details.result + ' :: ' + details.message);
+ }
+};
+
+const root = document.getElementById('root');
+const svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
+svgroot.id = 'svgroot';
+root.appendChild(svgroot);
+const svg = document.createElementNS(svgedit.NS.SVG, 'svg');
+svgroot.appendChild(svg);
+
+let elemId = 1;
+function setUp () {
+ // Mock out editor context.
+ svgedit.utilities.init({
+ getSVGRoot () { return svg; },
+ getDOMDocument () { return null; },
+ getDOMContainer () { return null; }
+ });
+ svgedit.coords.init({
+ getGridSnapping () { return false; },
+ getDrawing () {
+ return {
+ getNextId () { return '' + elemId++; }
+ };
}
+ });
+}
+
+function tearDown () {
+ while (svg.hasChildNodes()) {
+ svg.removeChild(svg.firstChild);
+ }
+}
+
+test('Test remapElement(translate) for rect', function () {
+ expect(4);
+
+ setUp();
+
+ const rect = document.createElementNS(svgedit.NS.SVG, 'rect');
+ rect.setAttribute('x', '200');
+ rect.setAttribute('y', '150');
+ rect.setAttribute('width', '250');
+ rect.setAttribute('height', '120');
+ svg.appendChild(rect);
+
+ const attrs = {
+ x: '200',
+ y: '150',
+ width: '125',
+ height: '75'
};
- var root = document.getElementById('root');
- var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
- svgroot.id = 'svgroot';
- root.appendChild(svgroot);
- var svg = document.createElementNS(svgedit.NS.SVG, 'svg');
- svgroot.appendChild(svg);
- var elemId = 1;
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 1; m.b = 0;
+ m.c = 0; m.d = 1;
+ m.e = 100; m.f = -50;
- function setUp () {
- // Mock out editor context.
- svgedit.utilities.init({
- getSVGRoot: function () { return svg; },
- getDOMDocument: function () { return null; },
- getDOMContainer: function () { return null; }
- });
- svgedit.coords.init({
- getGridSnapping: function () { return false; },
- getDrawing: function () {
- return {
- getNextId: function () { return '' + elemId++; }
- };
- }
- });
- }
+ svgedit.coords.remapElement(rect, attrs, m);
- function tearDown () {
- while (svg.hasChildNodes()) {
- svg.removeChild(svg.firstChild);
- }
- }
+ equals(rect.getAttribute('x'), '300');
+ equals(rect.getAttribute('y'), '100');
+ equals(rect.getAttribute('width'), '125');
+ equals(rect.getAttribute('height'), '75');
- test('Test remapElement(translate) for rect', function () {
- expect(4);
-
- setUp();
-
- var rect = document.createElementNS(svgedit.NS.SVG, 'rect');
- rect.setAttribute('x', '200');
- rect.setAttribute('y', '150');
- rect.setAttribute('width', '250');
- rect.setAttribute('height', '120');
- svg.appendChild(rect);
-
- var attrs = {
- x: '200',
- y: '150',
- width: '125',
- height: '75'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 1; m.b = 0;
- m.c = 0; m.d = 1;
- m.e = 100; m.f = -50;
-
- svgedit.coords.remapElement(rect, attrs, m);
-
- equals(rect.getAttribute('x'), '300');
- equals(rect.getAttribute('y'), '100');
- equals(rect.getAttribute('width'), '125');
- equals(rect.getAttribute('height'), '75');
-
- tearDown();
- });
-
- test('Test remapElement(scale) for rect', function () {
- expect(4);
- setUp();
-
- var rect = document.createElementNS(svgedit.NS.SVG, 'rect');
- rect.setAttribute('width', '250');
- rect.setAttribute('height', '120');
- svg.appendChild(rect);
-
- var attrs = {
- x: '0',
- y: '0',
- width: '250',
- height: '120'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 2; m.b = 0;
- m.c = 0; m.d = 0.5;
- m.e = 0; m.f = 0;
-
- svgedit.coords.remapElement(rect, attrs, m);
-
- equals(rect.getAttribute('x'), '0');
- equals(rect.getAttribute('y'), '0');
- equals(rect.getAttribute('width'), '500');
- equals(rect.getAttribute('height'), '60');
-
- tearDown();
- });
-
- test('Test remapElement(translate) for circle', function () {
- expect(3);
- setUp();
-
- var circle = document.createElementNS(svgedit.NS.SVG, 'circle');
- circle.setAttribute('cx', '200');
- circle.setAttribute('cy', '150');
- circle.setAttribute('r', '125');
- svg.appendChild(circle);
-
- var attrs = {
- cx: '200',
- cy: '150',
- r: '125'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 1; m.b = 0;
- m.c = 0; m.d = 1;
- m.e = 100; m.f = -50;
-
- svgedit.coords.remapElement(circle, attrs, m);
-
- equals(circle.getAttribute('cx'), '300');
- equals(circle.getAttribute('cy'), '100');
- equals(circle.getAttribute('r'), '125');
-
- tearDown();
- });
-
- test('Test remapElement(scale) for circle', function () {
- expect(3);
- setUp();
-
- var circle = document.createElementNS(svgedit.NS.SVG, 'circle');
- circle.setAttribute('cx', '200');
- circle.setAttribute('cy', '150');
- circle.setAttribute('r', '250');
- svg.appendChild(circle);
-
- var attrs = {
- cx: '200',
- cy: '150',
- r: '250'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 2; m.b = 0;
- m.c = 0; m.d = 0.5;
- m.e = 0; m.f = 0;
-
- svgedit.coords.remapElement(circle, attrs, m);
-
- equals(circle.getAttribute('cx'), '400');
- equals(circle.getAttribute('cy'), '75');
- // Radius is the minimum that fits in the new bounding box.
- equals(circle.getAttribute('r'), '125');
-
- tearDown();
- });
-
- test('Test remapElement(translate) for ellipse', function () {
- expect(4);
- setUp();
-
- var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse');
- ellipse.setAttribute('cx', '200');
- ellipse.setAttribute('cy', '150');
- ellipse.setAttribute('rx', '125');
- ellipse.setAttribute('ry', '75');
- svg.appendChild(ellipse);
-
- var attrs = {
- cx: '200',
- cy: '150',
- rx: '125',
- ry: '75'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 1; m.b = 0;
- m.c = 0; m.d = 1;
- m.e = 100; m.f = -50;
-
- svgedit.coords.remapElement(ellipse, attrs, m);
-
- equals(ellipse.getAttribute('cx'), '300');
- equals(ellipse.getAttribute('cy'), '100');
- equals(ellipse.getAttribute('rx'), '125');
- equals(ellipse.getAttribute('ry'), '75');
-
- tearDown();
- });
-
- test('Test remapElement(scale) for ellipse', function () {
- expect(4);
- setUp();
-
- var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse');
- ellipse.setAttribute('cx', '200');
- ellipse.setAttribute('cy', '150');
- ellipse.setAttribute('rx', '250');
- ellipse.setAttribute('ry', '120');
- svg.appendChild(ellipse);
-
- var attrs = {
- cx: '200',
- cy: '150',
- rx: '250',
- ry: '120'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 2; m.b = 0;
- m.c = 0; m.d = 0.5;
- m.e = 0; m.f = 0;
-
- svgedit.coords.remapElement(ellipse, attrs, m);
-
- equals(ellipse.getAttribute('cx'), '400');
- equals(ellipse.getAttribute('cy'), '75');
- equals(ellipse.getAttribute('rx'), '500');
- equals(ellipse.getAttribute('ry'), '60');
-
- tearDown();
- });
-
- test('Test remapElement(translate) for line', function () {
- expect(4);
- setUp();
-
- var line = document.createElementNS(svgedit.NS.SVG, 'line');
- line.setAttribute('x1', '50');
- line.setAttribute('y1', '100');
- line.setAttribute('x2', '120');
- line.setAttribute('y2', '200');
- svg.appendChild(line);
-
- var attrs = {
- x1: '50',
- y1: '100',
- x2: '120',
- y2: '200'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 1; m.b = 0;
- m.c = 0; m.d = 1;
- m.e = 100; m.f = -50;
-
- svgedit.coords.remapElement(line, attrs, m);
-
- equals(line.getAttribute('x1'), '150');
- equals(line.getAttribute('y1'), '50');
- equals(line.getAttribute('x2'), '220');
- equals(line.getAttribute('y2'), '150');
-
- tearDown();
- });
-
- test('Test remapElement(scale) for line', function () {
- expect(4);
- setUp();
-
- var line = document.createElementNS(svgedit.NS.SVG, 'line');
- line.setAttribute('x1', '50');
- line.setAttribute('y1', '100');
- line.setAttribute('x2', '120');
- line.setAttribute('y2', '200');
- svg.appendChild(line);
-
- var attrs = {
- x1: '50',
- y1: '100',
- x2: '120',
- y2: '200'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 2; m.b = 0;
- m.c = 0; m.d = 0.5;
- m.e = 0; m.f = 0;
-
- svgedit.coords.remapElement(line, attrs, m);
-
- equals(line.getAttribute('x1'), '100');
- equals(line.getAttribute('y1'), '50');
- equals(line.getAttribute('x2'), '240');
- equals(line.getAttribute('y2'), '100');
-
- tearDown();
- });
-
- test('Test remapElement(translate) for text', function () {
- expect(2);
- setUp();
-
- var text = document.createElementNS(svgedit.NS.SVG, 'text');
- text.setAttribute('x', '50');
- text.setAttribute('y', '100');
- svg.appendChild(text);
-
- var attrs = {
- x: '50',
- y: '100'
- };
-
- // Create a translate.
- var m = svg.createSVGMatrix();
- m.a = 1; m.b = 0;
- m.c = 0; m.d = 1;
- m.e = 100; m.f = -50;
-
- svgedit.coords.remapElement(text, attrs, m);
-
- equals(text.getAttribute('x'), '150');
- equals(text.getAttribute('y'), '50');
-
- tearDown();
- });
+ tearDown();
+});
+
+test('Test remapElement(scale) for rect', function () {
+ expect(4);
+ setUp();
+
+ const rect = document.createElementNS(svgedit.NS.SVG, 'rect');
+ rect.setAttribute('width', '250');
+ rect.setAttribute('height', '120');
+ svg.appendChild(rect);
+
+ const attrs = {
+ x: '0',
+ y: '0',
+ width: '250',
+ height: '120'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 2; m.b = 0;
+ m.c = 0; m.d = 0.5;
+ m.e = 0; m.f = 0;
+
+ svgedit.coords.remapElement(rect, attrs, m);
+
+ equals(rect.getAttribute('x'), '0');
+ equals(rect.getAttribute('y'), '0');
+ equals(rect.getAttribute('width'), '500');
+ equals(rect.getAttribute('height'), '60');
+
+ tearDown();
+});
+
+test('Test remapElement(translate) for circle', function () {
+ expect(3);
+ setUp();
+
+ const circle = document.createElementNS(svgedit.NS.SVG, 'circle');
+ circle.setAttribute('cx', '200');
+ circle.setAttribute('cy', '150');
+ circle.setAttribute('r', '125');
+ svg.appendChild(circle);
+
+ const attrs = {
+ cx: '200',
+ cy: '150',
+ r: '125'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 1; m.b = 0;
+ m.c = 0; m.d = 1;
+ m.e = 100; m.f = -50;
+
+ svgedit.coords.remapElement(circle, attrs, m);
+
+ equals(circle.getAttribute('cx'), '300');
+ equals(circle.getAttribute('cy'), '100');
+ equals(circle.getAttribute('r'), '125');
+
+ tearDown();
+});
+
+test('Test remapElement(scale) for circle', function () {
+ expect(3);
+ setUp();
+
+ const circle = document.createElementNS(svgedit.NS.SVG, 'circle');
+ circle.setAttribute('cx', '200');
+ circle.setAttribute('cy', '150');
+ circle.setAttribute('r', '250');
+ svg.appendChild(circle);
+
+ const attrs = {
+ cx: '200',
+ cy: '150',
+ r: '250'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 2; m.b = 0;
+ m.c = 0; m.d = 0.5;
+ m.e = 0; m.f = 0;
+
+ svgedit.coords.remapElement(circle, attrs, m);
+
+ equals(circle.getAttribute('cx'), '400');
+ equals(circle.getAttribute('cy'), '75');
+ // Radius is the minimum that fits in the new bounding box.
+ equals(circle.getAttribute('r'), '125');
+
+ tearDown();
+});
+
+test('Test remapElement(translate) for ellipse', function () {
+ expect(4);
+ setUp();
+
+ const ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse');
+ ellipse.setAttribute('cx', '200');
+ ellipse.setAttribute('cy', '150');
+ ellipse.setAttribute('rx', '125');
+ ellipse.setAttribute('ry', '75');
+ svg.appendChild(ellipse);
+
+ const attrs = {
+ cx: '200',
+ cy: '150',
+ rx: '125',
+ ry: '75'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 1; m.b = 0;
+ m.c = 0; m.d = 1;
+ m.e = 100; m.f = -50;
+
+ svgedit.coords.remapElement(ellipse, attrs, m);
+
+ equals(ellipse.getAttribute('cx'), '300');
+ equals(ellipse.getAttribute('cy'), '100');
+ equals(ellipse.getAttribute('rx'), '125');
+ equals(ellipse.getAttribute('ry'), '75');
+
+ tearDown();
+});
+
+test('Test remapElement(scale) for ellipse', function () {
+ expect(4);
+ setUp();
+
+ const ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse');
+ ellipse.setAttribute('cx', '200');
+ ellipse.setAttribute('cy', '150');
+ ellipse.setAttribute('rx', '250');
+ ellipse.setAttribute('ry', '120');
+ svg.appendChild(ellipse);
+
+ const attrs = {
+ cx: '200',
+ cy: '150',
+ rx: '250',
+ ry: '120'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 2; m.b = 0;
+ m.c = 0; m.d = 0.5;
+ m.e = 0; m.f = 0;
+
+ svgedit.coords.remapElement(ellipse, attrs, m);
+
+ equals(ellipse.getAttribute('cx'), '400');
+ equals(ellipse.getAttribute('cy'), '75');
+ equals(ellipse.getAttribute('rx'), '500');
+ equals(ellipse.getAttribute('ry'), '60');
+
+ tearDown();
+});
+
+test('Test remapElement(translate) for line', function () {
+ expect(4);
+ setUp();
+
+ const line = document.createElementNS(svgedit.NS.SVG, 'line');
+ line.setAttribute('x1', '50');
+ line.setAttribute('y1', '100');
+ line.setAttribute('x2', '120');
+ line.setAttribute('y2', '200');
+ svg.appendChild(line);
+
+ const attrs = {
+ x1: '50',
+ y1: '100',
+ x2: '120',
+ y2: '200'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 1; m.b = 0;
+ m.c = 0; m.d = 1;
+ m.e = 100; m.f = -50;
+
+ svgedit.coords.remapElement(line, attrs, m);
+
+ equals(line.getAttribute('x1'), '150');
+ equals(line.getAttribute('y1'), '50');
+ equals(line.getAttribute('x2'), '220');
+ equals(line.getAttribute('y2'), '150');
+
+ tearDown();
+});
+
+test('Test remapElement(scale) for line', function () {
+ expect(4);
+ setUp();
+
+ const line = document.createElementNS(svgedit.NS.SVG, 'line');
+ line.setAttribute('x1', '50');
+ line.setAttribute('y1', '100');
+ line.setAttribute('x2', '120');
+ line.setAttribute('y2', '200');
+ svg.appendChild(line);
+
+ const attrs = {
+ x1: '50',
+ y1: '100',
+ x2: '120',
+ y2: '200'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 2; m.b = 0;
+ m.c = 0; m.d = 0.5;
+ m.e = 0; m.f = 0;
+
+ svgedit.coords.remapElement(line, attrs, m);
+
+ equals(line.getAttribute('x1'), '100');
+ equals(line.getAttribute('y1'), '50');
+ equals(line.getAttribute('x2'), '240');
+ equals(line.getAttribute('y2'), '100');
+
+ tearDown();
+});
+
+test('Test remapElement(translate) for text', function () {
+ expect(2);
+ setUp();
+
+ const text = document.createElementNS(svgedit.NS.SVG, 'text');
+ text.setAttribute('x', '50');
+ text.setAttribute('y', '100');
+ svg.appendChild(text);
+
+ const attrs = {
+ x: '50',
+ y: '100'
+ };
+
+ // Create a translate.
+ const m = svg.createSVGMatrix();
+ m.a = 1; m.b = 0;
+ m.c = 0; m.d = 1;
+ m.e = 100; m.f = -50;
+
+ svgedit.coords.remapElement(text, attrs, m);
+
+ equals(text.getAttribute('x'), '150');
+ equals(text.getAttribute('y'), '50');
+
+ tearDown();
});
diff --git a/test/draw_test.html b/test/draw_test.html
index d96dc822..fbc7a72e 100644
--- a/test/draw_test.html
+++ b/test/draw_test.html
@@ -5,7 +5,7 @@
Unit Tests for draw.js
-
+
@@ -16,7 +16,7 @@
-
+
diff --git a/test/draw_test.js b/test/draw_test.js
index 71ded63f..56e8dc5d 100644
--- a/test/draw_test.js
+++ b/test/draw_test.js
@@ -1,793 +1,792 @@
/* eslint-env qunit */
-/* globals $, svgedit, equals */
-/* eslint-disable no-var, no-redeclare */
-$(function () {
- // log function
- QUnit.log = function (details) {
- if (window.console && window.console.log) {
- window.console.log(details.result + ' :: ' + details.message);
- }
- };
- var NS = svgedit.NS;
- var LAYER_CLASS = svgedit.draw.Layer.CLASS_NAME;
- var NONCE = 'foo';
- var LAYER1 = 'Layer 1';
- var LAYER2 = 'Layer 2';
- var LAYER3 = 'Layer 3';
- var PATH_ATTR = {
- // clone will convert relative to absolute, so the test for equality fails.
- // 'd': 'm7.38867,57.38867c0,-27.62431 22.37569,-50 50,-50c27.62431,0 50,22.37569 50,50c0,27.62431 -22.37569,50 -50,50c-27.62431,0 -50,-22.37569 -50,-50z',
- 'd': 'M7.389,57.389C7.389,29.764 29.764,7.389 57.389,7.389C85.013,7.389 107.389,29.764 107.389,57.389C107.389,85.013 85.013,107.389 57.389,107.389C29.764,107.389 7.389,85.013 7.389,57.389z',
- 'transform': 'rotate(45 57.388671875000036,57.388671874999986) ',
- 'stroke-width': '5',
- 'stroke': '#660000',
- 'fill': '#ff0000'
- };
+/* globals svgedit, equals */
- var svg = document.createElementNS(NS.SVG, 'svg');
- var sandbox = document.getElementById('sandbox');
- // Firefox throws exception in getBBox() when svg is not attached to DOM.
- sandbox.appendChild(svg);
+// log function
+QUnit.log = function (details) {
+ if (window.console && window.console.log) {
+ window.console.log(details.result + ' :: ' + details.message);
+ }
+};
+const {NS} = svgedit;
+const LAYER_CLASS = svgedit.draw.Layer.CLASS_NAME;
+const NONCE = 'foo';
+const LAYER1 = 'Layer 1';
+const LAYER2 = 'Layer 2';
+const LAYER3 = 'Layer 3';
+const PATH_ATTR = {
+ // clone will convert relative to absolute, so the test for equality fails.
+ // 'd': 'm7.38867,57.38867c0,-27.62431 22.37569,-50 50,-50c27.62431,0 50,22.37569 50,50c0,27.62431 -22.37569,50 -50,50c-27.62431,0 -50,-22.37569 -50,-50z',
+ 'd': 'M7.389,57.389C7.389,29.764 29.764,7.389 57.389,7.389C85.013,7.389 107.389,29.764 107.389,57.389C107.389,85.013 85.013,107.389 57.389,107.389C29.764,107.389 7.389,85.013 7.389,57.389z',
+ 'transform': 'rotate(45 57.388671875000036,57.388671874999986) ',
+ 'stroke-width': '5',
+ 'stroke': '#660000',
+ 'fill': '#ff0000'
+};
- // Set up