').append(btn.title);
}
} else if (btn.list) {
// Add button to list
button.addClass('push_button');
$$b('#' + btn.list + '_opts').append(button);
if (btn.isDefault) {
$$b('#cur_' + btn.list).append(button.children().clone());
var _svgicon = btn.svgicon || btn.id;
placementObj['#cur_' + btn.list] = _svgicon;
}
} else if (btn.includeWith) {
// Add to flyout menu / make flyout menu
var opts = btn.includeWith;
// opts.button, default, position
refBtn = $$b(opts.button);
flyoutHolder = refBtn.parent();
// Create a flyout menu if there isn't one already
var _tlsId = void 0;
if (!refBtn.parent().hasClass('tools_flyout')) {
// Create flyout placeholder
_tlsId = refBtn[0].id.replace('tool_', 'tools_');
showBtn = refBtn.clone().attr('id', _tlsId + '_show').append($$b('
', { class: 'flyout_arrow_horiz' }));
refBtn.before(showBtn);
// Create a flyout div
flyoutHolder = makeFlyoutHolder(_tlsId, refBtn);
}
refData = Actions.getButtonData(opts.button);
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
var curH = holders['#' + flyoutHolder[0].id] = [{
sel: '#' + id,
fn: btn.events.click,
icon: btn.id,
key: btn.key,
isDefault: Boolean(btn.includeWith && btn.includeWith.isDefault)
}, refData];
// {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
var pos = 'position' in opts ? opts.position : 'last';
var 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
$$b.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) {
$$b(document).bind('keydown', btn.key, func);
if (btn.title) {
button.attr('title', btn.title + ' [' + btn.key + ']');
}
}
} else {
button.bind(name, func);
}
});
}
setupFlyouts(holders);
});
$$b.each(btnSelects, function () {
addAltDropDown(this.elem, this.list, this.callback, { seticon: true });
});
if (svgicons) {
return new Promise(function (resolve, reject) {
$$b.svgIcons(svgicons, {
w: 24, h: 24,
id_match: false,
no_img: !isWebkit(),
fallback: fallbackObj,
placement: placementObj,
callback: function callback(icons) {
// Non-ideal hack to make the icon match the current size
// if (curPrefs.iconsize && curPrefs.iconsize !== 'm') {
if ($$b.pref('iconsize') !== 'm') {
prepResize();
}
runCallback();
resolve();
}
});
});
}
}
return runCallback();
};
var getPaint = function getPaint(color, opac, type) {
// update the editor's fill paint
var opts = { alpha: opac };
if (color.startsWith('url(#')) {
var refElem = svgCanvas.getRefElem(color);
if (refElem) {
refElem = refElem.cloneNode(true);
} else {
refElem = $$b('#' + type + '_color defs *')[0];
}
opts[refElem.tagName] = refElem;
} else if (color.startsWith('#')) {
opts.solidColor = color.substr(1);
} else {
opts.solidColor = 'none';
}
return new $$b.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) {
if (!data.output) {
// Ignore Chrome
return;
}
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
}
if (!exportWindow || exportWindow.closed) {
$$b.alert(uiStrings$1.notification.popupWindowBlocked);
return;
}
exportWindow.location.href = data.output;
});
svgCanvas.bind('zoomed', zoomChanged);
svgCanvas.bind('zoomDone', zoomDone);
svgCanvas.bind('updateCanvas',
/**
* @param {external:Window} win
* @param {false} center
* @param {module:math.XYObject} newCtr
* @listens module:svgcanvas.SvgCanvas#event:updateCanvas
* @returns {undefined}
*/
function (win, _ref14) {
var center = _ref14.center,
newCtr = _ref14.newCtr;
updateCanvas(center, newCtr);
});
svgCanvas.bind('contextset', contextChanged);
svgCanvas.bind('extension_added', extAdded);
svgCanvas.textActions.setInputElem($$b('#text')[0]);
var str = '
';
$$b.each(palette, function (i, item) {
str += '
';
});
$$b('#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 = '';
$$b.each(colorBlocks, function () {
str += '
';
});
$$b('#bg_blocks').append(str);
var blocks = $$b('#bg_blocks div');
var curBg = 'cur_background';
blocks.each(function () {
var blk = $$b(this);
blk.click(function () {
blocks.removeClass(curBg);
$$b(this).addClass(curBg);
});
});
setBackground($$b.pref('bkgd_color'), $$b.pref('bkgd_url'));
$$b('#image_save_opts input').val([$$b.pref('img_save')]);
var changeRectRadius = function changeRectRadius(ctl) {
svgCanvas.setRectRadius(ctl.value);
};
var changeFontSize = function changeFontSize(ctl) {
svgCanvas.setFontSize(ctl.value);
};
var changeStrokeWidth = function changeStrokeWidth(ctl) {
var val = ctl.value;
if (val === 0 && selectedElement && ['line', 'polyline'].includes(selectedElement.nodeName)) {
val = ctl.value = 1;
}
svgCanvas.setStrokeWidth(val);
};
var changeRotationAngle = function changeRotationAngle(ctl) {
svgCanvas.setRotationAngle(ctl.value);
$$b('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0);
};
var changeOpacity = function changeOpacity(ctl, val) {
if (val == null) {
val = ctl.value;
}
$$b('#group_opacity').val(val);
if (!ctl || !ctl.handle) {
$$b('#opac_slider').slider('option', 'value', val);
}
svgCanvas.setOpacity(val / 100);
};
var changeBlur = function changeBlur(ctl, val, noUndo) {
if (val == null) {
val = ctl.value;
}
$$b('#blur').val(val);
var complete = false;
if (!ctl || !ctl.handle) {
$$b('#blur_slider').slider('option', 'value', val);
complete = true;
}
if (noUndo) {
svgCanvas.setBlurNoUndo(val);
} else {
svgCanvas.setBlur(val, complete);
}
};
$$b('#stroke_style').change(function () {
svgCanvas.setStrokeAttr('stroke-dasharray', $$b(this).val());
operaRepaint();
});
$$b('#stroke_linejoin').change(function () {
svgCanvas.setStrokeAttr('stroke-linejoin', $$b(this).val());
operaRepaint();
});
// Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
$$b('select').change(function () {
$$b(this).blur();
});
// fired when user wants to move elements to another layer
var promptMoveLayerOnce = false;
$$b('#selLayerNames').change(function () {
var destLayer = this.options[this.selectedIndex].value;
var confirmStr = uiStrings$1.notification.QmoveElemsToLayer.replace('%s', destLayer);
var moveToLayer = function moveToLayer(ok) {
if (!ok) {
return;
}
promptMoveLayerOnce = true;
svgCanvas.moveSelectedToLayer(destLayer);
svgCanvas.clearSelection();
populateLayers();
};
if (destLayer) {
if (promptMoveLayerOnce) {
moveToLayer(true);
} else {
$$b.confirm(confirmStr, moveToLayer);
}
}
});
$$b('#font_family').change(function () {
svgCanvas.setFontFamily(this.value);
});
$$b('#seg_type').change(function () {
svgCanvas.setSegType($$b(this).val());
});
$$b('#text').bind('keyup input', function () {
svgCanvas.setTextContent(this.value);
});
$$b('#image_url').change(function () {
setImageURL(this.value);
});
$$b('#link_url').change(function () {
if (this.value.length) {
svgCanvas.setLinkURL(this.value);
} else {
svgCanvas.removeHyperlink();
}
});
$$b('#g_title').change(function () {
svgCanvas.setGroupTitle(this.value);
});
$$b('.attr_changer').change(function () {
var attr = this.getAttribute('data-attr');
var val = this.value;
var valid = isValidUnit(attr, val, selectedElement);
if (!valid) {
$$b.alert(uiStrings$1.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
var 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();
});
// Prevent selection of elements when shift-clicking
$$b('#palette').mouseover(function () {
var inp = $$b('
');
$$b(this).append(inp);
inp.focus().remove();
});
$$b('.palette_item').mousedown(function (evt) {
// shift key or right click for stroke
var picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill';
var color = $$b(this).data('rgb');
var paint = void 0;
// Webkit-based browsers returned 'initial' here for no stroke
if (color === 'none' || color === 'transparent' || color === 'initial') {
color = 'none';
paint = new $$b.jGraduate.Paint();
} else {
paint = new $$b.jGraduate.Paint({ alpha: 100, solidColor: color.substr(1) });
}
paintBox[picker].setPaint(paint);
svgCanvas.setColor(picker, color);
if (color !== 'none' && svgCanvas.getPaintOpacity(picker) !== 1) {
svgCanvas.setPaintOpacity(picker, 1.0);
}
updateToolButtonState();
}).bind('contextmenu', function (e) {
e.preventDefault();
});
$$b('#toggle_stroke_tools').on('click', function () {
$$b('#tools_bottom').toggleClass('expanded');
});
(function () {
var wArea = workarea[0];
var lastX = null,
lastY = null,
panning = false,
keypan = false;
$$b('#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;
return false;
}
});
$$b(window).mouseup(function () {
panning = false;
});
$$b(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);
}
});
/**
* @param {boolean} active
* @returns {undefined}
*/
editor.setPanning = function (active) {
svgCanvas.spaceKey = keypan = active;
};
})();
(function () {
var button = $$b('#main_icon');
var overlay = $$b('#main_icon span');
var list = $$b('#main_menu');
var onButton = false;
var height = 0;
var jsHover = true;
var setClick = false;
/*
// Currently unused
const hideMenu = function () {
list.fadeOut(200);
};
*/
$$b(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;
$$b(evt.target).click(function () {
list.css('margin-left', '-9999px').show();
});
}
}
onButton = false;
}).mousedown(function (evt) {
// $('.contextMenu').hide();
var islib = $$b(evt.target).closest('div.tools_flyout, .contextMenu').length;
if (!islib) {
$$b('.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 = $$b('#main_menu li');
// Check if JS method of hovering needs to be used (Webkit bug)
listItems.mouseover(function () {
jsHover = $$b(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.
/**
* See {@link http://api.jquery.com/bind/#bind-eventType-eventData-handler}
* @callback module:SVGEditor.DropDownCallback
* @param {external:jQuery.Event} ev See {@link http://api.jquery.com/Types/#Event}
* @listens external:jQuery.Event
* @returns {undefined|boolean} Calls `preventDefault()` and `stopPropagation()`
*/
/**
* @param {Element|string} elem DOM Element or selector
* @param {module:SVGEditor.DropDownCallback} callback Mouseup callback
* @param {boolean} dropUp
* @returns {undefined}
*/
editor.addDropDown = function (elem, callback, dropUp) {
if (!$$b(elem).length) {
return;
} // Quit if called on non-existent element
var button = $$b(elem).find('button');
var list = $$b(elem).find('ul').attr('id', $$b(elem)[0].id + '-list');
if (dropUp) {
$$b(elem).addClass('dropup');
} else {
// Move list to place where it can overflow container
$$b('#option_lists').append(list);
}
list.find('li').bind('mouseup', callback);
var onButton = false;
$$b(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 = $$b(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 () {
$$b('#font_family').val($$b(this).text()).change();
});
editor.addDropDown('#opacity_dropdown', function () {
if ($$b(this).find('div').length) {
return;
}
var perc = parseInt($$b(this).text().split('%')[0], 10);
changeOpacity(false, perc);
}, true);
// For slider usage, see: http://jqueryui.com/demos/slider/
$$b('#opac_slider').slider({
start: function start() {
$$b('#opacity_dropdown li:not(.special)').hide();
},
stop: function stop() {
$$b('#opacity_dropdown li').show();
$$b(window).mouseup();
},
slide: function slide(evt, ui) {
changeOpacity(ui);
}
});
editor.addDropDown('#blur_dropdown', $$b.noop);
var slideStart = false;
$$b('#blur_slider').slider({
max: 10,
step: 0.1,
stop: function stop(evt, ui) {
slideStart = false;
changeBlur(ui);
$$b('#blur_dropdown li').show();
$$b(window).mouseup();
},
start: function start() {
slideStart = true;
},
slide: function slide(evt, ui) {
changeBlur(ui, null, slideStart);
}
});
editor.addDropDown('#zoom_dropdown', function () {
var item = $$b(this);
var 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 () {
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 = void 0;
var unfocus = function unfocus() {
$$b(inp).blur();
};
$$b('#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') {
$$b('#text').focus();
}
});
})();
var clickFHPath = function clickFHPath() {
if (toolButtonClick('#tool_fhpath')) {
svgCanvas.setMode('fhpath');
}
};
var clickLine = function clickLine() {
if (toolButtonClick('#tool_line')) {
svgCanvas.setMode('line');
}
};
var clickSquare = function clickSquare() {
if (toolButtonClick('#tool_square')) {
svgCanvas.setMode('square');
}
};
var clickRect = function clickRect() {
if (toolButtonClick('#tool_rect')) {
svgCanvas.setMode('rect');
}
};
var clickFHRect = function clickFHRect() {
if (toolButtonClick('#tool_fhrect')) {
svgCanvas.setMode('fhrect');
}
};
var clickCircle = function clickCircle() {
if (toolButtonClick('#tool_circle')) {
svgCanvas.setMode('circle');
}
};
var clickEllipse = function clickEllipse() {
if (toolButtonClick('#tool_ellipse')) {
svgCanvas.setMode('ellipse');
}
};
var clickFHEllipse = function clickFHEllipse() {
if (toolButtonClick('#tool_fhellipse')) {
svgCanvas.setMode('fhellipse');
}
};
var clickImage = function clickImage() {
if (toolButtonClick('#tool_image')) {
svgCanvas.setMode('image');
}
};
var clickZoom = function clickZoom() {
if (toolButtonClick('#tool_zoom')) {
svgCanvas.setMode('zoom');
workarea.css('cursor', zoomInIcon);
}
};
var zoomImage = function zoomImage(multiplier) {
var res = svgCanvas.getResolution();
multiplier = multiplier ? res.zoom * multiplier : 1;
// setResolution(res.w * multiplier, res.h * multiplier, true);
$$b('#zoom').val(multiplier * 100);
svgCanvas.setZoom(multiplier);
zoomDone();
updateCanvas(true);
};
var dblclickZoom = function dblclickZoom() {
if (toolButtonClick('#tool_zoom')) {
zoomImage();
setSelectMode();
}
};
var clickText = function clickText() {
if (toolButtonClick('#tool_text')) {
svgCanvas.setMode('text');
}
};
var clickPath = function clickPath() {
if (toolButtonClick('#tool_path')) {
svgCanvas.setMode('path');
}
};
// Delete is a contextual tool that only appears in the ribbon if
// an element has been selected
var deleteSelected = function deleteSelected() {
if (selectedElement != null || multiselected) {
svgCanvas.deleteSelectedElements();
}
};
var cutSelected = function cutSelected() {
if (selectedElement != null || multiselected) {
svgCanvas.cutSelectedElements();
}
};
var copySelected = function copySelected() {
if (selectedElement != null || multiselected) {
svgCanvas.copySelectedElements();
}
};
var pasteInCenter = function pasteInCenter() {
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 moveToTopSelected() {
if (selectedElement != null) {
svgCanvas.moveToTopSelectedElement();
}
};
var moveToBottomSelected = function moveToBottomSelected() {
if (selectedElement != null) {
svgCanvas.moveToBottomSelectedElement();
}
};
var moveUpDownSelected = function moveUpDownSelected(dir) {
if (selectedElement != null) {
svgCanvas.moveUpDownSelected(dir);
}
};
var convertToPath$$1 = function convertToPath$$1() {
if (selectedElement != null) {
svgCanvas.convertToPath();
}
};
var reorientPath = function reorientPath() {
if (selectedElement != null) {
path.reorient();
}
};
var makeHyperlink = function makeHyperlink() {
if (selectedElement != null || multiselected) {
$$b.prompt(uiStrings$1.notification.enterNewLinkURL, 'http://', function (url) {
if (url) {
svgCanvas.makeHyperlink(url);
}
});
}
};
var moveSelected = function moveSelected(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;
}
svgCanvas.moveSelectedElements(dx, dy);
}
};
var linkControlPoints = function linkControlPoints() {
$$b('#tool_node_link').toggleClass('push_button_pressed tool_button');
var linked = $$b('#tool_node_link').hasClass('push_button_pressed');
path.linkControlPoints(linked);
};
var clonePathNode = function clonePathNode() {
if (path.getNodePoint()) {
path.clonePathNode();
}
};
var deletePathNode = function deletePathNode() {
if (path.getNodePoint()) {
path.deletePathNode();
}
};
var addSubPath = function addSubPath() {
var button = $$b('#tool_add_subpath');
var sp = !button.hasClass('push_button_pressed');
button.toggleClass('push_button_pressed tool_button');
path.addSubPath(sp);
};
var opencloseSubPath = function opencloseSubPath() {
path.opencloseSubPath();
};
var selectNext = function selectNext() {
svgCanvas.cycleElement(1);
};
var selectPrev = function selectPrev() {
svgCanvas.cycleElement(0);
};
var rotateSelected = function rotateSelected(cw, step) {
if (selectedElement == null || multiselected) {
return;
}
if (!cw) {
step *= -1;
}
var angle = parseFloat($$b('#angle').val()) + step;
svgCanvas.setRotationAngle(angle);
updateContextPanel();
};
/**
* @fires module:svgcanvas.SvgCanvas#event:ext-onNewDocument
* @returns {undefined}
*/
var clickClear = function clickClear() {
var _curConfig$dimensions = slicedToArray(curConfig.dimensions, 2),
x = _curConfig$dimensions[0],
y = _curConfig$dimensions[1];
$$b.confirm(uiStrings$1.notification.QwantToClear, function (ok) {
if (!ok) {
return;
}
setSelectMode();
svgCanvas.clear();
svgCanvas.setResolution(x, y);
updateCanvas(true);
zoomImage();
populateLayers();
updateContextPanel();
prepPaints();
svgCanvas.runExtensions('onNewDocument');
});
};
var clickBold = function clickBold() {
svgCanvas.setBold(!svgCanvas.getBold());
updateContextPanel();
return false;
};
var clickItalic = function clickItalic() {
svgCanvas.setItalic(!svgCanvas.getItalic());
updateContextPanel();
return false;
};
var clickSave = function clickSave() {
// In the future, more options can be provided here
var saveOpts = {
images: $$b.pref('img_save'),
round_digits: 6
};
svgCanvas.save(saveOpts);
};
var loadingURL = void 0;
var clickExport = function clickExport() {
$$b.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 () {
var _ref15 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(imgType) {
var exportWindowName, openExportWindow, chrome, quality;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
openExportWindow = function openExportWindow() {
var str = uiStrings$1.notification.loadingImage;
if (curConfig.exportWindowType === 'new') {
editor.exportWindowCt++;
}
exportWindowName = curConfig.canvasName + editor.exportWindowCt;
var popHTML = void 0,
popURL = void 0;
if (loadingURL) {
popURL = loadingURL;
} else {
popHTML = '\n \n
\n
' + str + '\n \n
' + str + '
\n ';
if (typeof URL !== 'undefined' && URL.createObjectURL) {
var blob = new Blob([popHTML], { type: 'text/html' });
popURL = URL.createObjectURL(blob);
} else {
popURL = 'data:text/html;base64;charset=utf-8,' + encode64(popHTML);
}
loadingURL = popURL;
}
exportWindow = window.open(popURL, exportWindowName);
};
if (imgType) {
_context5.next = 3;
break;
}
return _context5.abrupt('return');
case 3:
// Open placeholder window (prevents popup)
exportWindowName = void 0;
chrome = isChrome();
if (!(imgType === 'PDF')) {
_context5.next = 10;
break;
}
if (!customExportPDF && !chrome) {
openExportWindow();
}
svgCanvas.exportPDF(exportWindowName, chrome ? 'save' : undefined);
_context5.next = 14;
break;
case 10:
if (!customExportImage) {
openExportWindow();
}
quality = parseInt($$b('#image-slider').val(), 10) / 100;
/* const results = */
_context5.next = 14;
return svgCanvas.rasterExport(imgType, quality, exportWindowName);
case 14:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
return function (_x5) {
return _ref15.apply(this, arguments);
};
}(), function () {
var sel = $$b(this);
if (sel.val() === 'JPEG' || sel.val() === 'WEBP') {
if (!$$b('#image-slider').length) {
$$b('
').appendTo(sel.parent());
}
} else {
$$b('#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 clickOpen() {
svgCanvas.open();
};
var clickImport = function clickImport() {};
var clickUndo = function clickUndo() {
if (undoMgr.getUndoStackSize() > 0) {
undoMgr.undo();
populateLayers();
}
};
var clickRedo = function clickRedo() {
if (undoMgr.getRedoStackSize() > 0) {
undoMgr.redo();
populateLayers();
}
};
var clickGroup = function clickGroup() {
// group
if (multiselected) {
svgCanvas.groupSelectedElements();
// ungroup
} else if (selectedElement) {
svgCanvas.ungroupSelectedElement();
}
};
var clickClone = function clickClone() {
svgCanvas.cloneSelectedElements(20, 20);
};
var clickAlign = function clickAlign() {
var letter = this.id.replace('tool_align', '').charAt(0);
svgCanvas.alignSelectedElements(letter, $$b('#align_relative_to').val());
};
var clickWireframe = function clickWireframe() {
$$b('#tool_wireframe').toggleClass('push_button_pressed tool_button');
workarea.toggleClass('wireframe');
if (supportsNonSS) {
return;
}
var wfRules = $$b('#wireframe_rules');
if (!wfRules.length) {
/* wfRules = */$$b('').appendTo('head');
} else {
wfRules.empty();
}
updateWireFrame();
};
$$b('#svg_docprops_container, #svg_prefs_container').draggable({
cancel: 'button,fieldset',
containment: 'window'
}).css('position', 'absolute');
var docprops = false;
var preferences = false;
var showDocProperties = function showDocProperties() {
if (docprops) {
return;
}
docprops = true;
// This selects the correct radio button by using the array notation
$$b('#image_save_opts input').val([$$b.pref('img_save')]);
// update resolution option with actual resolution
var res = svgCanvas.getResolution();
if (curConfig.baseUnit !== 'px') {
res.w = convertUnit(res.w) + curConfig.baseUnit;
res.h = convertUnit(res.h) + curConfig.baseUnit;
}
$$b('#canvas_width').val(res.w);
$$b('#canvas_height').val(res.h);
$$b('#canvas_title').val(svgCanvas.getDocumentTitle());
$$b('#svg_docprops').show();
};
var showPreferences = function showPreferences() {
if (preferences) {
return;
}
preferences = true;
$$b('#main_menu').hide();
// Update background color with current one
var blocks = $$b('#bg_blocks div');
var curBg = 'cur_background';
var canvasBg = curPrefs.bkgd_color;
var url = $$b.pref('bkgd_url');
blocks.each(function () {
var blk = $$b(this);
var isBg = blk.css('background-color') === canvasBg;
blk.toggleClass(curBg, isBg);
if (isBg) {
$$b('#canvas_bg_url').removeClass(curBg);
}
});
if (!canvasBg) {
blocks.eq(0).addClass(curBg);
}
if (url) {
$$b('#canvas_bg_url').val(url);
}
$$b('#grid_snapping_on').prop('checked', curConfig.gridSnapping);
$$b('#grid_snapping_step').attr('value', curConfig.snappingStep);
$$b('#grid_color').attr('value', curConfig.gridColor);
$$b('#svg_prefs').show();
};
var hideSourceEditor = function hideSourceEditor() {
$$b('#svg_source_editor').hide();
editingsource = false;
$$b('#svg_source_textarea').blur();
};
var saveSourceEditor = function saveSourceEditor() {
if (!editingsource) {
return;
}
var saveChanges = function saveChanges() {
svgCanvas.clearSelection();
hideSourceEditor();
zoomImage();
populateLayers();
updateTitle();
prepPaints();
};
if (!svgCanvas.setSvgString($$b('#svg_source_textarea').val())) {
$$b.confirm(uiStrings$1.notification.QerrorsRevertToSource, function (ok) {
if (!ok) {
return false;
}
saveChanges();
});
} else {
saveChanges();
}
setSelectMode();
};
var hideDocProperties = function hideDocProperties() {
$$b('#svg_docprops').hide();
$$b('#canvas_width,#canvas_height').removeAttr('disabled');
$$b('#resolution')[0].selectedIndex = 0;
$$b('#image_save_opts input').val([$$b.pref('img_save')]);
docprops = false;
};
var hidePreferences = function hidePreferences() {
$$b('#svg_prefs').hide();
preferences = false;
};
var saveDocProperties = function saveDocProperties() {
// set title
var newTitle = $$b('#canvas_title').val();
updateTitle(newTitle);
svgCanvas.setDocumentTitle(newTitle);
// update resolution
var width = $$b('#canvas_width'),
w = width.val();
var height = $$b('#canvas_height'),
h = height.val();
if (w !== 'fit' && !isValidUnit('width', w)) {
$$b.alert(uiStrings$1.notification.invalidAttrValGiven);
width.parent().addClass('error');
return false;
}
width.parent().removeClass('error');
if (h !== 'fit' && !isValidUnit('height', h)) {
$$b.alert(uiStrings$1.notification.invalidAttrValGiven);
height.parent().addClass('error');
return false;
}
height.parent().removeClass('error');
if (!svgCanvas.setResolution(w, h)) {
$$b.alert(uiStrings$1.notification.noContentToFitTo);
return false;
}
// Set image save option
$$b.pref('img_save', $$b('#image_save_opts :checked').val());
updateCanvas();
hideDocProperties();
};
/**
* Save user preferences based on current values in the UI
* @function module:SVGEditor.savePreferences
* @returns {undefined}
*/
var savePreferences = editor.savePreferences = function () {
// Set background
var color = $$b('#bg_blocks div.cur_background').css('background-color') || '#FFF';
setBackground(color, $$b('#canvas_bg_url').val());
// set language
var lang = $$b('#lang_select').val();
if (lang !== $$b.pref('lang')) {
editor.putLocale(lang, goodLangs, curConfig);
}
// set icon size
setIconSize($$b('#iconsize').val());
// set grid setting
curConfig.gridSnapping = $$b('#grid_snapping_on')[0].checked;
curConfig.snappingStep = $$b('#grid_snapping_step').val();
curConfig.gridColor = $$b('#grid_color').val();
curConfig.showRulers = $$b('#show_rulers')[0].checked;
$$b('#rulers').toggle(curConfig.showRulers);
if (curConfig.showRulers) {
updateRulers();
}
curConfig.baseUnit = $$b('#base_unit').val();
svgCanvas.setConfig(curConfig);
updateCanvas();
hidePreferences();
};
var resetScrollPos = $$b.noop;
var cancelOverlays = function cancelOverlays() {
$$b('#dialog_box').hide();
if (!editingsource && !docprops && !preferences) {
if (curContext) {
svgCanvas.leaveContext();
}
return;
}
if (editingsource) {
if (origSource !== $$b('#svg_source_textarea').val()) {
$$b.confirm(uiStrings$1.notification.QignoreSourceChanges, function (ok) {
if (ok) {
hideSourceEditor();
}
});
} else {
hideSourceEditor();
}
} else if (docprops) {
hideDocProperties();
} else if (preferences) {
hidePreferences();
}
resetScrollPos();
};
var winWh = { width: $$b(window).width(), height: $$b(window).height() };
// Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
if (isIE()) {
(function () {
resetScrollPos = function resetScrollPos() {
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
};
$$b(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
};
});
})();
}
$$b(window).resize(function (evt) {
$$b.each(winWh, function (type, val) {
var curval = $$b(window)[type]();
workarea[0]['scroll' + (type === 'width' ? 'Left' : 'Top')] -= (curval - val) / 2;
winWh[type] = curval;
});
setFlyoutPositions();
});
(function () {
workarea.scroll(function () {
// TODO: jQuery's scrollLeft/Top() wouldn't require a null check
if ($$b('#ruler_x').length) {
$$b('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;
}
if ($$b('#ruler_y').length) {
$$b('#ruler_y')[0].scrollTop = workarea[0].scrollTop;
}
});
})();
$$b('#url_notice').click(function () {
$$b.alert(this.title);
});
$$b('#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 () {
var toolnames = ['clear', 'open', 'save', 'source', 'delete', 'delete_multi', 'paste', 'clone', 'clone_multi', 'move_top', 'move_bottom'];
var curClass = 'tool_button_current';
var allTools = '';
$$b.each(toolnames, function (i, item) {
allTools += (i ? ',' : '') + '#tool_' + item;
});
$$b(allTools).mousedown(function () {
$$b(this).addClass(curClass);
}).bind('mousedown mouseout', function () {
$$b(this).removeClass(curClass);
});
$$b('#tool_undo, #tool_redo').mousedown(function () {
if (!$$b(this).hasClass('disabled')) {
$$b(this).addClass(curClass);
}
}).bind('mousedown mouseout', function () {
$$b(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 (isMac() && !window.opera) {
var shortcutButtons = ['tool_clear', 'tool_save', 'tool_source', 'tool_undo', 'tool_redo', 'tool_clone'];
var _i2 = shortcutButtons.length;
while (_i2--) {
var button = document.getElementById(shortcutButtons[_i2]);
if (button) {
var title = button.title;
var 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 colorPicker(elem) {
var picker = elem.attr('id') === 'stroke_color' ? 'stroke' : 'fill';
// const opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
var title = picker === 'stroke' ? uiStrings$1.ui.pick_stroke_paint_opacity : uiStrings$1.ui.pick_fill_paint_opacity;
// let wasNone = false; // Currently unused
var pos = elem.offset();
var paint = paintBox[picker].paint;
$$b('#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 $$b.jGraduate.Paint(p);
paintBox[picker].setPaint(paint);
svgCanvas.setPaint(picker, paint);
$$b('#color_picker').hide();
}, function () {
$$b('#color_picker').hide();
});
};
var PaintBox = function PaintBox(container, type) {
var paintColor = void 0,
paintOpacity = void 0;
var 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 = $$b(container)[0].appendChild(document.importNode(docElem, true));
docElem.setAttribute('width', 16.5);
this.rect = docElem.firstElementChild;
this.defs = docElem.getElementsByTagName('defs')[0];
this.grad = this.defs.firstElementChild;
this.paint = new $$b.jGraduate.Paint({ solidColor: cur.color });
this.type = type;
this.setPaint = function (paint, apply) {
this.paint = paint;
var ptype = paint.type;
var opac = paint.alpha / 100;
var fillAttr = 'none';
switch (ptype) {
case 'solidColor':
fillAttr = paint[ptype] !== 'none' ? '#' + paint[ptype] : paint[ptype];
break;
case 'linearGradient':
case 'radialGradient':
this.grad.remove();
this.grad = this.defs.appendChild(paint[ptype]);
var id = this.grad.id = 'gradbox_' + this.type;
fillAttr = 'url(#' + id + ')';
break;
}
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 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 childs = selectedElement.getElementsByTagName('*');
var gPaint = null;
for (var _i3 = 0, len = childs.length; _i3 < len; _i3++) {
var elem = childs[_i3];
var p = elem.getAttribute(type);
if (_i3 === 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 $$b.jGraduate.Paint({ copy: this.paint });
svgCanvas.setPaint(type, paint);
break;
}
};
};
paintBox.fill = new PaintBox('#fill_color', 'fill');
paintBox.stroke = new PaintBox('#stroke_color', 'stroke');
$$b('#stroke_width').val(curConfig.initStroke.width);
$$b('#group_opacity').val(curConfig.initOpacity * 100);
// Use this SVG elem to test vectorEffect support
var testEl = paintBox.fill.rect.cloneNode(false);
testEl.setAttribute('style', 'vector-effect:non-scaling-stroke');
var 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(NS.SVG, 'feGaussianBlur');
if (blurTest.stdDeviationX === undefined) {
$$b('#tool_blur').hide();
}
$$b(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
$$b('#image_save_opts [value=embed]').attr('disabled', 'disabled');
$$b('#image_save_opts input').val(['ref']);
$$b.pref('img_save', 'ref');
$$b('#image_opt_embed').css('color', '#666').attr('title', uiStrings$1.notification.featNotSupported);
}
});
}, 1000);
$$b('#fill_color, #tool_fill .icon_label').click(function () {
colorPicker($$b('#fill_color'));
updateToolButtonState();
});
$$b('#stroke_color, #tool_stroke .icon_label').click(function () {
colorPicker($$b('#stroke_color'));
updateToolButtonState();
});
$$b('#group_opacityLabel').click(function () {
$$b('#opacity_dropdown button').mousedown();
$$b(window).mouseup();
});
$$b('#zoomLabel').click(function () {
$$b('#zoom_dropdown button').mousedown();
$$b(window).mouseup();
});
$$b('#tool_move_top').mousedown(function (evt) {
$$b('#tools_stacking').show();
evt.preventDefault();
});
$$b('.layer_button').mousedown(function () {
$$b(this).addClass('layer_buttonpressed');
}).mouseout(function () {
$$b(this).removeClass('layer_buttonpressed');
}).mouseup(function () {
$$b(this).removeClass('layer_buttonpressed');
});
$$b('.push_button').mousedown(function () {
if (!$$b(this).hasClass('disabled')) {
$$b(this).addClass('push_button_pressed').removeClass('push_button');
}
}).mouseout(function () {
$$b(this).removeClass('push_button_pressed').addClass('push_button');
}).mouseup(function () {
$$b(this).removeClass('push_button_pressed').addClass('push_button');
});
// ask for a layer name
$$b('#layer_new').click(function () {
var uniqName = void 0,
i = svgCanvas.getCurrentDrawing().getNumLayers();
do {
uniqName = uiStrings$1.layers.layer + ' ' + ++i;
} while (svgCanvas.getCurrentDrawing().hasLayer(uniqName));
$$b.prompt(uiStrings$1.notification.enterUniqueLayerName, uniqName, function (newName) {
if (!newName) {
return;
}
if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
$$b.alert(uiStrings$1.notification.dupeLayerName);
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)
$$b('#layerlist tr.layer').removeClass('layersel');
$$b('#layerlist tr.layer:first').addClass('layersel');
}
}
function cloneLayer() {
var name = svgCanvas.getCurrentDrawing().getCurrentLayerName() + ' copy';
$$b.prompt(uiStrings$1.notification.enterUniqueLayerName, name, function (newName) {
if (!newName) {
return;
}
if (svgCanvas.getCurrentDrawing().hasLayer(newName)) {
$$b.alert(uiStrings$1.notification.dupeLayerName);
return;
}
svgCanvas.cloneLayer(newName);
updateContextPanel();
populateLayers();
});
}
function mergeLayer() {
if ($$b('#layerlist tr.layersel').index() === svgCanvas.getCurrentDrawing().getNumLayers() - 1) {
return;
}
svgCanvas.mergeLayer();
updateContextPanel();
populateLayers();
}
function moveLayer(pos) {
var total = svgCanvas.getCurrentDrawing().getNumLayers();
var curIndex = $$b('#layerlist tr.layersel').index();
if (curIndex > 0 || curIndex < total - 1) {
curIndex += pos;
svgCanvas.setCurrentLayerPosition(total - curIndex - 1);
populateLayers();
}
}
$$b('#layer_delete').click(deleteLayer);
$$b('#layer_up').click(function () {
moveLayer(-1);
});
$$b('#layer_down').click(function () {
moveLayer(1);
});
$$b('#layer_rename').click(function () {
// const curIndex = $('#layerlist tr.layersel').prevAll().length; // Currently unused
var oldName = $$b('#layerlist tr.layersel td.layername').text();
$$b.prompt(uiStrings$1.notification.enterNewLayerName, '', function (newName) {
if (!newName) {
return;
}
if (oldName === newName || svgCanvas.getCurrentDrawing().hasLayer(newName)) {
$$b.alert(uiStrings$1.notification.layerHasThatName);
return;
}
svgCanvas.renameCurrentLayer(newName);
populateLayers();
});
});
var SIDEPANEL_MAXWIDTH = 300;
var SIDEPANEL_OPENWIDTH = 150;
var sidedrag = -1,
sidedragging = false,
allowmove = false;
/**
* @param {Float} delta
* @fires module:svgcanvas.SvgCanvas#event:ext-workareaResized
* @returns {undefined}
*/
var changeSidePanelWidth = function changeSidePanelWidth(delta) {
var rulerX = $$b('#ruler_x');
$$b('#sidepanels').width('+=' + delta);
$$b('#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 resizeSidePanel(evt) {
if (!allowmove) {
return;
}
if (sidedrag === -1) {
return;
}
sidedragging = true;
var deltaX = sidedrag - evt.pageX;
var sideWidth = $$b('#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
* @param {boolean} close Forces the side panel closed
* @returns {undefined}
*/
var toggleSidePanel = function toggleSidePanel(close) {
var w = $$b('#sidepanels').width();
var deltaX = (w > 2 || close ? 2 : SIDEPANEL_OPENWIDTH) - w;
changeSidePanelWidth(deltaX);
};
$$b('#sidepanel_handle').mousedown(function (evt) {
sidedrag = evt.pageX;
$$b(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;
});
$$b(window).mouseup(function () {
sidedrag = -1;
sidedragging = false;
$$b('#svg_editor').unbind('mousemove', resizeSidePanel);
});
populateLayers();
// function changeResolution (x,y) {
// const {zoom} = svgCanvas.getResolution();
// setResolution(x * zoom, y * zoom);
// }
var centerCanvas = function centerCanvas() {
// this centers the canvas vertically in the workarea (horizontal handled in CSS)
workarea.css('line-height', workarea.height() + 'px');
};
$$b(window).bind('load resize', centerCanvas);
function stepFontSize(elem, step) {
var origVal = Number(elem.value);
var sugVal = origVal + step;
var increasing = sugVal >= origVal;
if (step === 0) {
return origVal;
}
if (origVal >= 24) {
if (increasing) {
return Math.round(origVal * 1.1);
}
return Math.round(origVal / 1.1);
}
if (origVal <= 1) {
if (increasing) {
return origVal * 2;
}
return origVal / 2;
}
return sugVal;
}
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) {
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;
// // }
// }
$$b('#resolution').change(function () {
var wh = $$b('#canvas_width,#canvas_height');
if (!this.selectedIndex) {
if ($$b('#canvas_width').val() === 'fit') {
wh.removeAttr('disabled').val(100);
}
} else if (this.value === 'content') {
wh.val('fit').attr('disabled', 'disabled');
} else {
var dims = this.value.split('x');
$$b('#canvas_width').val(dims[0]);
$$b('#canvas_height').val(dims[1]);
wh.removeAttr('disabled');
}
});
// Prevent browser from erroneously repopulating fields
$$b('input,select').attr('autocomplete', 'off');
/**
* Associate all button actions as well as non-button keyboard shortcuts
* @namespace {PlainObject} module:SVGEditor~Actions
*/
var Actions = function () {
/**
* @typedef {PlainObject} module:SVGEditor.ToolButton
* @property {string} sel The CSS selector for the tool
* @property {external:jQuery.Function} fn A handler to be attached to the `evt`
* @property {string} evt The event for which the `fn` listener will be added
* @property {module:SVGEditor.Key} [key] [key, preventDefault, NoDisableInInput]
* @property {string} [parent] Selector
* @property {boolean} [hidekey] Whether to show key value in title
* @property {string} [icon] The button ID
* @property {boolean} isDefault For flyout holders
*/
/**
*
* @name module:SVGEditor~ToolButtons
* @type {module:SVGEditor.ToolButton[]}
*/
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], parent: '#tools_line', prepend: 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 fn() {
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 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$$1, 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' },
// Shortcuts not associated with buttons
{ key: 'ctrl+left', fn: function fn() {
rotateSelected(0, 1);
}
}, { key: 'ctrl+right', fn: function fn() {
rotateSelected(1, 1);
}
}, { key: 'ctrl+shift+left', fn: function fn() {
rotateSelected(0, 5);
}
}, { key: 'ctrl+shift+right', fn: function fn() {
rotateSelected(1, 5);
}
}, { key: 'shift+O', fn: selectPrev }, { key: 'shift+P', fn: selectNext }, { key: [modKey + 'up', true], fn: function fn() {
zoomImage(2);
}
}, { key: [modKey + 'down', true], fn: function fn() {
zoomImage(0.5);
}
}, { key: [modKey + ']', true], fn: function fn() {
moveUpDownSelected('Up');
}
}, { key: [modKey + '[', true], fn: function fn() {
moveUpDownSelected('Down');
}
}, { key: ['up', true], fn: function fn() {
moveSelected(0, -1);
}
}, { key: ['down', true], fn: function fn() {
moveSelected(0, 1);
}
}, { key: ['left', true], fn: function fn() {
moveSelected(-1, 0);
}
}, { key: ['right', true], fn: function fn() {
moveSelected(1, 0);
}
}, { key: 'shift+up', fn: function fn() {
moveSelected(0, -10);
}
}, { key: 'shift+down', fn: function fn() {
moveSelected(0, 10);
}
}, { key: 'shift+left', fn: function fn() {
moveSelected(-10, 0);
}
}, { key: 'shift+right', fn: function fn() {
moveSelected(10, 0);
}
}, { key: ['alt+up', true], fn: function fn() {
svgCanvas.cloneSelectedElements(0, -1);
}
}, { key: ['alt+down', true], fn: function fn() {
svgCanvas.cloneSelectedElements(0, 1);
}
}, { key: ['alt+left', true], fn: function fn() {
svgCanvas.cloneSelectedElements(-1, 0);
}
}, { key: ['alt+right', true], fn: function fn() {
svgCanvas.cloneSelectedElements(1, 0);
}
}, { key: ['alt+shift+up', true], fn: function fn() {
svgCanvas.cloneSelectedElements(0, -10);
}
}, { key: ['alt+shift+down', true], fn: function fn() {
svgCanvas.cloneSelectedElements(0, 10);
}
}, { key: ['alt+shift+left', true], fn: function fn() {
svgCanvas.cloneSelectedElements(-10, 0);
}
}, { key: ['alt+shift+right', true], fn: function fn() {
svgCanvas.cloneSelectedElements(10, 0);
}
}, { key: 'A', fn: function fn() {
svgCanvas.selectAllInCurrentLayer();
}
},
// 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 {
/** @lends module:SVGEditor~Actions */
/**
* @returns {undefined}
*/
setAll: function setAll() {
var flyouts = {};
$$b.each(toolButtons, function (i, opts) {
// Bind function to button
var btn = void 0;
if (opts.sel) {
btn = $$b(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 && $$b(opts.parent + '_show').length) {
var fH = $$b(opts.parent);
if (!fH.length) {
fH = makeFlyoutHolder(opts.parent.substr(1));
}
if (opts.prepend) {
btn[0].style.margin = 'initial';
}
fH[opts.prepend ? 'prepend' : '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
var keyval = void 0,
// 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 += '';
var fn = opts.fn;
$$b.each(keyval.split('/'), function (i, key) {
$$b(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
$$b('.attr_changer, #image_url').bind('keydown', 'return', function (evt) {
$$b(this).change();
evt.preventDefault();
});
$$b(window).bind('keydown', 'tab', function (e) {
if (uiContext === 'canvas') {
e.preventDefault();
selectNext();
}
}).bind('keydown', 'shift+tab', function (e) {
if (uiContext === 'canvas') {
e.preventDefault();
selectPrev();
}
});
$$b('#tool_zoom').dblclick(dblclickZoom);
},
/**
* @returns {undefined}
*/
setTitles: function setTitles() {
$$b.each(keyAssocs, function (keyval, sel) {
var menu = $$b(sel).parents('#main_menu').length;
$$b(sel).each(function () {
var t = void 0;
if (menu) {
t = $$b(this).text().split(' [')[0];
} else {
t = this.title.split(' [')[0];
}
var keyStr = '';
// Shift+Up
$$b.each(keyval.split('/'), function (i, key) {
var modBits = key.split('+');
var mod = '';
if (modBits.length > 1) {
mod = modBits[0] + '+';
key = modBits[1];
}
keyStr += (i ? '/' : '') + mod + (uiStrings$1['key_' + key] || key);
});
if (menu) {
this.lastChild.textContent = t + ' [' + keyStr + ']';
} else {
this.title = t + ' [' + keyStr + ']';
}
});
});
},
/**
* @param {string} sel Selector to match
* @returns {module:SVGEditor.ToolButton}
*/
getButtonData: function getButtonData(sel) {
return Object.values(toolButtons).find(function (btn) {
return btn.sel === sel;
});
}
};
}();
// Select given tool
editor.ready(function () {
var tool = void 0;
var itool = curConfig.initTool,
container = $$b('#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 = $$b('#tool_select');
}
tool.click().mouseup();
if (curConfig.wireframe) {
$$b('#tool_wireframe').click();
}
if (curConfig.showlayers) {
toggleSidePanel();
}
$$b('#rulers').toggle(!!curConfig.showRulers);
if (curConfig.showRulers) {
$$b('#show_rulers')[0].checked = true;
}
if (curConfig.baseUnit) {
$$b('#base_unit').val(curConfig.baseUnit);
}
if (curConfig.gridSnapping) {
$$b('#grid_snapping_on')[0].checked = true;
}
if (curConfig.snappingStep) {
$$b('#grid_snapping_step').val(curConfig.snappingStep);
}
if (curConfig.gridColor) {
$$b('#grid_color').val(curConfig.gridColor);
}
});
// init SpinButtons
$$b('#rect_rx').SpinButton({ min: 0, max: 1000, stateObj: stateObj, callback: changeRectRadius });
$$b('#stroke_width').SpinButton({ min: 0, max: 99, smallStep: 0.1, stateObj: stateObj, callback: changeStrokeWidth });
$$b('#angle').SpinButton({ min: -180, max: 180, step: 5, stateObj: stateObj, callback: changeRotationAngle });
$$b('#font_size').SpinButton({ min: 0.001, stepfunc: stepFontSize, stateObj: stateObj, callback: changeFontSize });
$$b('#group_opacity').SpinButton({ min: 0, max: 100, step: 5, stateObj: stateObj, callback: changeOpacity });
$$b('#blur').SpinButton({ min: 0, max: 10, step: 0.1, stateObj: stateObj, callback: changeBlur });
$$b('#zoom').SpinButton({ min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, stateObj: stateObj, callback: changeZoom })
// Set default zoom
.val(svgCanvas.getZoom() * 100);
$$b('#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;
}
});
var lmenuFunc = function lmenuFunc(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;
}
};
$$b('#layerlist').contextMenu({
menu: 'cmenu_layers',
inSpeed: 0
}, lmenuFunc);
$$b('#layer_moreopts').contextMenu({
menu: 'cmenu_layers',
inSpeed: 0,
allowLeft: true
}, lmenuFunc);
$$b('.contextMenu li').mousedown(function (ev) {
ev.preventDefault();
});
$$b('#cmenu_canvas li').disableContextMenu();
canvMenu.enableContextMenuItems('#delete,#cut,#copy');
function enableOrDisableClipboard() {
var svgeditClipboard = void 0;
try {
svgeditClipboard = localStorage.getItem('svgedit_clipboard');
} catch (err) {}
canvMenu[(svgeditClipboard ? 'en' : 'dis') + 'ableContextMenuItems']('#paste,#paste_in_place');
}
enableOrDisableClipboard();
window.addEventListener('storage', function (e) {
if (e.key !== 'svgedit_clipboard') {
return;
}
enableOrDisableClipboard();
});
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$1.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
return uiStrings$1.notification.unsavedChanges;
}
}, false);
/**
* Expose the uiStrings
* @function module:SVGEditor.canvas.getUIStrings
* @returns {module:SVGEditor.uiStrings}
*/
editor.canvas.getUIStrings = function () {
return uiStrings$1;
};
/**
* @callback module:SVGEditor.OpenPrepCallback
* @param {boolean} noChanges
* @returns {undefined}
*/
/**
* @param {module:SVGEditor.OpenPrepCallback} func Confirmation dialog callback
* @returns {undefined}
*/
editor.openPrep = function (func) {
$$b('#main_menu').hide();
if (undoMgr.getUndoStackSize() === 0) {
func(true);
} else {
$$b.confirm(uiStrings$1.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: 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) {
var importImage = function importImage(e) {
$$b.process_cancel(uiStrings$1.notification.loadingImage);
e.stopPropagation();
e.preventDefault();
$$b('#workarea').removeAttr('style');
$$b('#main_menu').hide();
var file = e.type === 'drop' ? e.dataTransfer.files[0] : this.files[0];
if (!file) {
$$b('#dialog_box').hide();
return;
}
/* if (file.type === 'application/pdf') { // Todo: Handle PDF imports
}
else */
if (file.type.includes('image')) {
// Detected an image
// svg handling
var reader = void 0;
if (file.type.includes('svg')) {
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]);
$$b('#dialog_box').hide();
};
reader.readAsText(file);
} else {
// bitmap handling
reader = new FileReader();
reader.onloadend = function (_ref16) {
var result = _ref16.target.result;
// let's insert the new image until we know its dimensions
var insertNewImage = function insertNewImage(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, result);
svgCanvas.selectOnly([newImage]);
svgCanvas.alignSelectedElements('m', 'page');
svgCanvas.alignSelectedElements('c', 'page');
updateContextPanel();
$$b('#dialog_box').hide();
};
// create dummy img so we know the default dimensions
var imgWidth = 100;
var imgHeight = 100;
var img = new Image();
img.style.opacity = 0;
img.onload = function () {
imgWidth = img.offsetWidth || img.naturalWidth || img.width;
imgHeight = img.offsetHeight || img.naturalHeight || img.height;
insertNewImage(imgWidth, imgHeight);
};
img.src = result;
};
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 = $$b('
').click(function () {
var f = this;
editor.openPrep(function (ok) {
if (!ok) {
return;
}
svgCanvas.clear();
if (f.files.length === 1) {
$$b.process_cancel(uiStrings$1.notification.loadingImage);
var reader = new FileReader();
reader.onloadend = function (e) {
loadSvgString(e.target.result);
updateCanvas();
};
reader.readAsText(f.files[0]);
}
});
});
$$b('#tool_open').show().prepend(open);
var imgImport = $$b('
').change(importImage);
$$b('#tool_import').show().prepend(imgImport);
}
// $(function () {
updateCanvas(true);
// });
// const revnums = 'svg-editor.js ($Rev$) ';
// revnums += svgCanvas.getVersion();
// $('#copyright')[0].setAttribute('title', revnums);
/**
* @function module:SVGEditor.setLang
* @param {string} lang The language code
* @param {module:locale.LocaleStrings} allStrings See {@tutorial LocaleDocs}
* @fires module:svgcanvas.SvgCanvas#event:ext-langReady
* @fires module:svgcanvas.SvgCanvas#event:ext-langChanged
* @returns {undefined}
*/
var setLang = editor.setLang = function (lang, allStrings) {
editor.langChanged = true;
$$b.pref('lang', lang);
$$b('#lang_select').val(lang);
if (!allStrings) {
return;
}
$$b.extend(uiStrings$1, allStrings);
// const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
var oldLayerName = $$b('#layerlist tr.layersel td.layername').text();
var renameLayer = oldLayerName === uiStrings$1.common.layer + ' 1';
svgCanvas.setUiStrings(allStrings);
Actions.setTitles();
if (renameLayer) {
svgCanvas.renameCurrentLayer(uiStrings$1.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$1,
importLocale: getImportLocale({ defaultLang: lang, defaultName: ext.name })
});
}
} else {
svgCanvas.runExtensions('langReady', /** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */{ lang: lang, uiStrings: uiStrings$1 });
}
svgCanvas.runExtensions('langChanged', /** @type {module:svgcanvas.SvgCanvas#event:ext-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'
};
$$b.each(elems, function (source, dest) {
$$b(dest).attr('title', $$b(source)[0].title);
});
// Copy alignment titles
$$b('#multiselected_panel div[id^=tool_align]').each(function () {
$$b('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
};
init$7(
/**
* @implements {module:locale.LocaleEditorInit}
*/
{
/**
* Gets an array of results from extensions with a `addLangData` method
* returning an object with a `data` property set to its locales (to be
* merged with regular locales)
* @param {string} langParam
* @fires module:svgcanvas.SvgCanvas#event:ext-addLangData
* @todo Can we forego this in favor of `langReady` (or forego `langReady`)?
* @returns {module:locale.AddLangExtensionLocaleData[]}
*/
addLangData: function addLangData(langParam) {
return svgCanvas.runExtensions('addLangData',
/**
* @function
* @type {module:svgcanvas.ExtensionVarBuilder}
* @param {string} defaultLang
* @param {string} defaultName
* @returns {module:svgcanvas.SvgCanvas#event:ext-addLangData}
*/
function (name) {
// We pass in a function as we don't know the extension name here when defining this `addLangData` method
return {
lang: langParam,
importLocale: getImportLocale({ defaultLang: langParam, defaultName: name })
};
}, true);
},
curConfig: curConfig
});
// Load extensions
// Bit of a hack to run extensions in local Opera/IE9
if (document.location.protocol === 'file:') {
setTimeout(extAndLocaleFunc, 100);
} else {
// Returns a promise (if we wanted to fire 'extensions-loaded' event, potentially useful to hide interface as some extension locales are only available after this)
extAndLocaleFunc();
}
};
/**
* @callback module:SVGEditor.ReadyCallback
* @returns {undefined}
*/
/**
* Queues a callback to be invoked when the editor is ready (or
* to be invoked immediately if it is already ready--i.e.,
* if `svgEditor.runCallbacks` has been run)
* @param {module:SVGEditor.ReadyCallback} cb Callback to be queued to invoke
* @returns {undefined}
*/
editor.ready = function (cb) {
if (!isReady) {
callbacks.push(cb);
} else {
cb();
}
};
/**
* Invokes the callbacks previous set by `svgEditor.ready`
* @returns {undefined}
*/
editor.runCallbacks = function () {
callbacks.forEach(function (cb) {
cb();
});
isReady = true;
};
/**
* @param {string} str The SVG string to load
* @returns {undefined}
*/
editor.loadFromString = function (str) {
editor.ready(function () {
loadSvgString(str);
});
};
/**
* Not presently in use
* @param {PlainObject} featList
* @returns {undefined}
*/
editor.disableUI = function (featList) {
// $(function () {
// $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove();
// $('#tools_top').css('left', 5);
// });
};
/**
* @callback module:SVGEditor.URLLoadCallback
* @param {boolean} success
* @returns {undefined}
*/
/**
* @param {string} url URL from which to load an SVG string via Ajax
* @param {PlainObject} [opts] May contain properties: `cache`, `callback`
* @param {boolean} opts.cache
* @param {module:SVGEditor.URLLoadCallback} opts.callback Invoked with `true` or `false` depending on success
* @returns {undefined}
*/
editor.loadFromURL = function (url, opts) {
if (!opts) {
opts = {};
}
var _opts = opts,
cache = _opts.cache,
cb = _opts.callback;
editor.ready(function () {
$$b.ajax({
url: url,
dataType: 'text',
cache: !!cache,
beforeSend: function beforeSend() {
$$b.process_cancel(uiStrings$1.notification.loadingImage);
},
success: function success(str) {
loadSvgString(str, cb);
},
error: function error(xhr, stat, err) {
if (xhr.status !== 404 && xhr.responseText) {
loadSvgString(xhr.responseText, cb);
} else {
$$b.alert(uiStrings$1.notification.URLloadFail + ': \n' + err, cb);
}
},
complete: function complete() {
$$b('#dialog_box').hide();
}
});
});
};
/**
* @param {string} str The Data URI to base64-decode (if relevant) and load
* @returns {undefined}
*/
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)?)?,/);
}
if (pre) {
pre = pre[0];
}
var src = str.slice(pre.length);
loadSvgString(base64 ? decode64(src) : decodeURIComponent(src));
});
};
/**
* @param {string} name Used internally; no need for i18n.
* @param {module:svgcanvas.ExtensionInitCallback} init Config to be invoked on this module
* @param {module:SVGEditor~ImportLocale} importLocale Importer defaulting to pth with current extension name and locale
* @throws {Error} If called too early
* @returns {Promise} Resolves to `undefined`
*/
editor.addExtension = function (name, init$$1, importLocale) {
// 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) {
throw new Error('Extension added too early');
}
return svgCanvas.addExtension.call(this, name, init$$1, importLocale);
// });
};
// Defer injection to wait out initial menu processing. This probably goes
// away once all context menu behavior is brought to context menu.
editor.ready(function () {
injectExtendedContextMenuItemsIntoDom();
});
var extensionsAdded = false;
var messageQueue = [];
/**
* @param {Any} data
* @param {string} origin
* @fires module:svgcanvas.SvgCanvas#event:message
* @returns {undefined}
*/
var messageListener = function messageListener(_ref17) {
var data = _ref17.data,
origin = _ref17.origin;
// console.log('data, origin, extensionsAdded', data, origin, extensionsAdded);
var messageObj = { data: data, origin: origin };
if (!extensionsAdded) {
messageQueue.push(messageObj);
} else {
// Extensions can handle messages at this stage with their own
// canvas `message` listeners
svgCanvas.call('message', messageObj);
}
};
window.addEventListener('message', messageListener);
// Run init once DOM is loaded
// jQuery(editor.init);
Promise.resolve().then(function () {
// We wait a micro-task to let the svgEditor variable be defined for module checks
editor.init();
});
// TO BUILD AN IIFE VERSION OF THIS FILE (AS CAN WORK ON OLDER BROWSERS),
window.svgEditor = editor;
window.svgEditor.modules = false;
// URL OVERRIDE CONFIG
editor.setConfig({
/**
To override the ability for URLs to set URL-based SVG content,
uncomment the following:
*/
// preventURLContentLoading: true,
/**
To override the ability for URLs to set other configuration (including
extension config), uncomment the following:
*/
// preventAllURLConfig: true,
/**
To override the ability for URLs to set their own extensions,
uncomment the following (note that if `setConfig()` is used in
extension code, it will still be additive to extensions,
however):
*/
// lockExtensions: true,
});
editor.setConfig({
/*
Provide default values here which differ from that of the editor but
which the URL can override
*/
}, { allowInitialUserOverride: true });
// EXTENSION CONFIG
editor.setConfig({
extensions: [
// 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js'
], noDefaultExtensions: false // noDefaultExtensions can only be meaningfully used in svgedit-config-iife.js or in the URL
});
// STYLESHEET CONFIG
editor.setConfig({
stylesheets: ['@default', '../svgedit-custom.css']
});
// OTHER CONFIG
editor.setConfig({
// canvasName: 'default',
// canvas_expansion: 3,
// initFill: {
// color: 'FF0000', // solid red
// opacity: 1
// },
// initStroke: {
// width: 5,
// color: '000000', // solid black
// opacity: 1
// },
// initOpacity: 1,
// colorPickerCSS: null,
// initTool: 'select',
// exportWindowType: 'new', // 'same'
// wireframe: false,
// showlayers: false,
// no_save_warning: false,
// PATH CONFIGURATION
// imgPath: 'images/',
// langPath: 'locale/',
// extPath: 'extensions/',
// jGraduatePath: 'jgraduate/images/',
/*
Uncomment the following to allow at least same domain (embedded) access,
including `file:///` access.
Setting as `['*']` would allow any domain to access but would be unsafe to
data privacy and integrity.
*/
// allowedOrigins: [location.origin || 'null'], // May be 'null' (as a string) when used as a `file:///` URL
// DOCUMENT PROPERTIES
// dimensions: [640, 480],
// EDITOR OPTIONS
// gridSnapping: false,
// gridColor: '#000',
// baseUnit: 'px',
// snappingStep: 10,
// showRulers: true,
// EXTENSION-RELATED (GRID)
// showGrid: false, // Set by ext-grid.js
// EXTENSION-RELATED (STORAGE)
// noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage
// forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not
// emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store
});
// PREF CHANGES
/**
setConfig() can also be used to set preferences in addition to
configuration (see defaultPrefs in svg-editor.js for a list of
possible settings), but at least if you are using ext-storage.js
to store preferences, it will probably be better to let your
users control these.
As with configuration, one may use allowInitialUserOverride, but
in the case of preferences, any previously stored preferences
will also thereby be enabled to override this setting (and at a
higher priority than any URL preference setting overrides).
Failing to use allowInitialUserOverride will ensure preferences
are hard-coded here regardless of URL or prior user storage setting.
*/
editor.setConfig({
// lang: '', // Set dynamically within locale.js if not previously set
// iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise
/**
* When showing the preferences dialog, svg-editor.js currently relies
* on curPrefs instead of $.pref, so allowing an override for bkgd_color
* means that this value won't have priority over block auto-detection as
* far as determining which color shows initially in the preferences
* dialog (though it can be changed and saved).
*/
// bkgd_color: '#FFF',
// bkgd_url: '',
// img_save: 'embed',
// Only shows in UI as far as alert notices
// save_notice_done: false,
// export_notice_done: false
});
editor.setConfig({
// Indicate pref settings here if you wish to allow user storage or URL settings
// to be able to override your default preferences (unless other config options
// have already explicitly prevented one or the other)
}, { allowInitialUserOverride: true });
}());