- Enhancement (svgIcons): Fix JSDoc param def; add `alt` options

- Accessibility: Begin work, add aria-label to some buttons and
    form controls; add `role=main`; `<img alt>`; `<iframe title>`
- i18n: Add `lang` attribute
- Refactoring: lbs, simplify i18nized element retrieval call
- Docs: Some JSDoc descriptions, JSDoc spacing, fix svgIcons param
    def; add todo
- Testing: Avoid reporting meta-viewport (have own zooming
    controls and difficult to fix)
master
Brett Zamir 2019-04-03 12:49:48 +08:00
parent 69ea647286
commit 056f4f197c
36 changed files with 968 additions and 382 deletions

View File

@ -16,6 +16,11 @@
- Optimization fix: Properly run code conditionally on browser check;
fixes #312 (@ianli-sc)
- Enhancement: Add CAD Placemark extension (@NeiroNx)
- Enhancement (svgIcons): Fix JSDoc param def; add `alt` options
- Accessibility: Begin work, add aria-label to some buttons and
form controls; add `role=main`; `<img alt>`; `<iframe title>`
- i18n: Add `lang` attribute
- Refactoring: lbs, simplify i18nized element retrieval call
- Refactoring: Make dialog OK button retrievable locale-independently
via a `data-ok` attribute (using for testing)
- Linting (ESLint): Update polyfills to new compat rules of
@ -25,6 +30,10 @@
- Testing (UI Refactoring): Abstract out to helper file functions
- Testing (UI Refactoring): Avoid testing being locale-dependent;
approve storage (and set locale to English) before each test
- Testing: Avoid reporting meta-viewport (have own zooming
controls and difficult to fix)
- Docs: Some JSDoc descriptions, JSDoc spacing, fix svgIcons param
def; add todo
- npm: Update devDeps; update nested deps for security audit; remove
one unneeded)

View File

@ -2,7 +2,8 @@ var svgEditorExtensionLocale_server_moinsave_en = (function () {
'use strict';
var en = {
saved: 'Saved! Return to Item View!'
saved: 'Saved! Return to Item View!',
hiddenframe: 'Frame to store hidden values'
};
return en;

View File

@ -2,7 +2,8 @@ var svgEditorExtensionLocale_server_moinsave_zh_CN = (function () {
'use strict';
var zhCN = {
saved: '已保存! 返回视图!'
saved: '已保存! 返回视图!',
hiddenframe: 'Frame to store hidden values'
};
return zhCN;

View File

@ -2,7 +2,8 @@ var svgEditorExtensionLocale_server_opensave_en = (function () {
'use strict';
var en = {
uploading: 'Uploading...'
uploading: 'Uploading...',
hiddenframe: 'Frame to store hidden values'
};
return en;

View File

@ -2,7 +2,8 @@ var svgEditorExtensionLocale_server_opensave_zh_CN = (function () {
'use strict';
var zhCN = {
uploading: '正在上传...'
uploading: '正在上传...',
hiddenframe: 'Frame to store hidden values'
};
return zhCN;

View File

@ -4887,7 +4887,7 @@ var svgEditorExtension_server_moinsave = (function () {
/* const target = */
$('<iframe name="output_frame" style="width: 0; height: 0;" src="#"/>').appendTo('body');
$("<iframe name=\"output_frame\" title=\"".concat(strings.hiddenframe, "\"\n style=\"width: 0; height: 0;\" src=\"#\"/>")).appendTo('body');
svgEditor.setCustomHandlers({
save: function () {
var _save = _asyncToGenerator(

View File

@ -5017,7 +5017,7 @@ var svgEditorExtension_server_opensave = (function () {
cancelled = false; // Hiding by size instead of display to avoid FF console errors
// with `getBBox` in browser.js `supportsPathBBox_`)
$('<iframe name="output_frame" style="width: 0; height: 0;" src="#"/>').appendTo('body');
$("<iframe name=\"output_frame\" title=\"".concat(strings.hiddenframe, "\"\n style=\"width: 0; height: 0;\" src=\"#\"/>")).appendTo('body');
svgEditor.setCustomHandlers({
save: function save(win, data) {
var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data,

225
dist/index-es.js vendored
View File

@ -9626,6 +9626,10 @@ function jQueryPluginDBox($) {
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -9658,7 +9662,7 @@ function jQueryPluginDBox($) {
});
} else if (type === 'select') {
var div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $("<select aria-label=\"".concat(msg, "\">")).appendTo(div);
if (checkbox) {
var label = $('<label>').text(checkbox.label);
@ -22304,11 +22308,17 @@ function jQueryPluginSVGIcons($) {
var svgIcons = {};
var fixIDs;
/**
* List of raster images with each
* key being the SVG icon ID to replace, and the value the image file name
* Map of raster images with each key being the SVG icon ID
* to replace, and the value the image file name
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
*/
/**
* Map of raster images with each key being the SVG icon ID
* whose `alt` will be set, and the value being the `alt` text
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Alts
*/
/**
* @function external:jQuery.svgIcons
* @param {string} file The location of a local SVG or SVGz file
@ -22317,21 +22327,29 @@ function jQueryPluginSVGIcons($) {
* @param {Float} [opts.h] The icon heights
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
* @param {string} [opts.fallback_path] The path to use for all images
listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids
as values. This provides a custom method of adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with
corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>`
element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to
parse as XML. SVGZ files add compression benefits, but getting data from
them fails in Firefox 2 and older.
* listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will
* be replaced by, rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] Map with selectors
* for keys and SVG icon ids as values. This provides a custom method of
* adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] Map
* with selectors for keys and numbers as values. This allows an easy way to
* resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A
* function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match
* SVG icon ids with corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon
* into an `<img>` element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and
* thus not to parse as XML. SVGZ files add compression benefits, but
* getting data from them fails in Firefox 2 and older.
* @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key
* being the SVG icon ID whose `alt` will be set, and the value being
* the `alt` text
* @param {string} [opts.testIconAlt="icon"] Alt text for the injected test image.
* In case wish to ensure have one for accessibility
* @returns {undefined}
*/
@ -22442,7 +22460,8 @@ function jQueryPluginSVGIcons($) {
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
height: 0,
alt: opts.testIconAlt || 'icon'
}).appendTo('body').load(function () {
// Safari 4 crashes, Opera and Chrome don't
makeIcons(true);
@ -22460,7 +22479,7 @@ function jQueryPluginSVGIcons($) {
* @param {external:jQuery} target
* @param {external:jQuery} icon A wrapped `defs` or Image
* @param {string} id SVG icon ID
* @param {string} setID
* @param {boolean} setID Whether to set the ID attribute (with `id`)
* @returns {undefined}
*/
@ -22472,6 +22491,17 @@ function jQueryPluginSVGIcons($) {
if (setID) icon.attr('id', id);
var cl = target.attr('class');
if (cl) icon.attr('class', 'svg_icon ' + cl);
if (!target.alt) {
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon.attr('alt', alt);
}
target.replaceWith(icon);
} else {
target.append(icon);
@ -22522,12 +22552,18 @@ function jQueryPluginSVGIcons($) {
var path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
var icon = $(new Image()).attr({
class: 'svg_icon',
src: path + imgsrc,
width: iconW,
height: iconH,
alt: 'icon'
alt: alt
});
addIcon(icon, id);
});
@ -22570,9 +22606,16 @@ function jQueryPluginSVGIcons($) {
if (toImage) {
tempHolder.empty().append(svgroot);
var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon = $(new Image()).attr({
class: 'svg_icon',
src: str
src: str,
alt: alt
});
} else {
icon = fixIDs($(svgroot), i);
@ -22705,13 +22748,15 @@ function jQueryPluginSVGIcons($) {
*/
/**
* If a Float is used, it will represent width and height. Arrays contain the width and height.
* If a Float is used, it will represent width and height. Arrays contain
* the width and height.
* @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size
*/
/**
* @function external:jQuery.resizeSvgIcons
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with
* selectors as keys. The values are sizes.
* @returns {undefined}
*/
@ -28023,10 +28068,24 @@ var jPicker = function jPicker($) {
var $$a = jQuery;
var langParam;
/**
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj
* @param {boolean} ids
* @returns {undefined}
* Looks for elements to localize using the supplied `obj` to indicate
* on which selectors (or IDs if `ids` is set to `true`) to set its
* strings (with selectors relative to the editor root element). All
* keys will be translated, but for each selector, only the first item
* found matching will be modified.
* If the type is `content`, the selector-identified element's children
* will be checked, and the first (non-empty) text (placeholder) node
* found will have its text replaced.
* If the type is `title`, the element's `title`
* property will be set.
* If the type is `aria-label`, the element's `aria-label` attribute
* will be set (i.e., instructions for screen readers when there is
* otherwise no visible text to be read for the function of the form
* control).
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings
* @param {boolean} ids
* @returns {undefined}
*/
var setStrings = function setStrings(type, obj, ids) {
@ -28048,12 +28107,18 @@ var setStrings = function setStrings(type, obj, ids) {
var $elem = parent.find(sel);
if ($elem.length) {
var elem = parent.find(sel)[0];
var elem = $elem[0];
switch (type) {
case 'aria-label':
elem.setAttribute('aria-label', val);
break;
case 'content':
_toConsumableArray(elem.childNodes).some(function (node) {
if (node.nodeType === 3 && node.textContent.trim()) {
if (node.nodeType === 3
/* Node.TEXT_NODE */
&& node.textContent.trim()) {
node.textContent = val;
return true;
}
@ -28091,10 +28156,11 @@ var setStrings = function setStrings(type, obj, ids) {
var editor_;
/**
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
* @returns {undefined}
* Sets the current editor instance (on which `addLangData`) exists.
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
* @returns {undefined}
*/
var init$7 = function init(editor) {
@ -28119,7 +28185,7 @@ function () {
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(langData) {
var more, _langData, tools, properties, config, layers, common, ui, opts;
var more, _langData, tools, properties, config, layers, common, ui, opts, ariaLabels;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
@ -28146,6 +28212,7 @@ function () {
case 6:
_langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui;
setStrings('content', {
// Todo: Add this powered by (probably by default) but with config to remove
// copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html
curve_segments: properties.curve_segments,
fitToContent: tools.fitToContent,
@ -28203,14 +28270,41 @@ function () {
}, true); // Context menus
opts = {};
$$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () {
opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this];
['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'].forEach(function (item) {
opts['#cmenu_canvas a[href="#' + item + '"]'] = tools[item];
});
$$a.each(['dupe', 'merge_down', 'merge_all'], function () {
opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this];
['dupe', 'merge_down', 'merge_all'].forEach(function (item) {
opts['#cmenu_layers a[href="#' + item + '"]'] = layers[item];
});
opts['#cmenu_layers a[href="#delete"]'] = layers.del;
setStrings('content', opts);
ariaLabels = {};
Object.entries({
tool_blur: properties.blur,
tool_position: tools.align_to_page,
tool_font_family: properties.font_family,
zoom_panel: ui.zoom_level,
stroke_linejoin: properties.linejoin_miter,
stroke_linecap: properties.linecap_butt,
tool_opacity: properties.opacity
}).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
id = _ref5[0],
value = _ref5[1];
ariaLabels['#' + id + ' button'] = value;
});
Object.entries({
group_opacity: properties.opacity,
zoom: ui.zoom_level
}).forEach(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
id = _ref7[0],
value = _ref7[1];
ariaLabels['#' + id] = value;
});
setStrings('aria-label', ariaLabels);
setStrings('title', {
align_relative_to: tools.align_relative_to,
circle_cx: properties.circle_cx,
@ -28314,7 +28408,7 @@ function () {
langData: langData
});
case 15:
case 19:
case "end":
return _context.stop();
}
@ -28327,20 +28421,21 @@ function () {
};
}();
/**
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
* @param {{langPath: string}} conf
* @fires module:svgcanvas.SvgCanvas#event:ext-addLangData
* @fires module:svgcanvas.SvgCanvas#event:ext-langReady
* @fires module:svgcanvas.SvgCanvas#event:ext-langChanged
* @returns {Promise} Resolves to result of {@link module:locale.readLang}
*
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
* @param {{langPath: string}} conf
* @fires module:svgcanvas.SvgCanvas#event:ext-addLangData
* @fires module:svgcanvas.SvgCanvas#event:ext-langReady
* @fires module:svgcanvas.SvgCanvas#event:ext-langChanged
* @returns {Promise} Resolves to result of {@link module:locale.readLang}
*/
var putLocale =
/*#__PURE__*/
function () {
var _ref4 = _asyncToGenerator(
var _ref8 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) {
var url;
@ -28396,7 +28491,7 @@ function () {
}));
return function putLocale(_x2, _x3, _x4) {
return _ref4.apply(this, arguments);
return _ref8.apply(this, arguments);
};
}();
@ -29881,6 +29976,8 @@ editor.init = function () {
no_img: !isWebkit(),
// Opera & Firefox 4 gives odd behavior w/images
fallback_path: curConfig.imgPath,
// Todo: Set `alts: {}` with keys as the IDs in fallback set to
// `uiStrings` (localized) values
fallback: {
logo: 'logo.png',
select: 'select.png',
@ -31896,7 +31993,7 @@ editor.init = function () {
var _ref13 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee5(win, ext) {
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders;
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, altsObj, placementObj, holders;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
@ -32086,7 +32183,7 @@ editor.init = function () {
break;
}
fallbackObj = {}, placementObj = {}, holders = {};
fallbackObj = {}, altsObj = {}, placementObj = {}, holders = {};
/**
* @typedef {GenericArray} module:SVGEditor.KeyArray
* @property {string} 0 The key to bind (on `keydown`)
@ -32131,9 +32228,10 @@ editor.init = function () {
var icon;
if (!svgicons) {
icon = $$b('<img src="' + btn.icon + '">');
icon = $$b('<img src="' + btn.icon + (btn.title ? '" alt="' + btn.title : '') + '">');
} else {
fallbackObj[id] = btn.icon;
altsObj[id] = btn.title;
var svgicon = btn.svgicon || btn.id;
if (btn.type === 'app_menu') {
@ -36045,6 +36143,13 @@ editor.init = function () {
return _context17.abrupt("return");
case 5:
// Todo: Remove `allStrings.lang` property in locale in
// favor of just `lang`?
document.documentElement.lang = allStrings.lang; // lang;
// Todo: Add proper RTL Support!
// Todo: Use RTL detection instead and take out of locales?
// document.documentElement.dir = allStrings.dir;
$$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
@ -36060,11 +36165,11 @@ editor.init = function () {
if (!extsPreLang.length) {
_context17.next = 17;
_context17.next = 18;
break;
}
_context17.next = 14;
_context17.next = 15;
return Promise.all(extsPreLang.map(function (ext) {
loadedExtensionNames.push(ext.name);
return ext.langReady({
@ -36077,12 +36182,12 @@ editor.init = function () {
});
}));
case 14:
case 15:
extsPreLang.length = 0;
_context17.next = 18;
_context17.next = 19;
break;
case 17:
case 18:
loadedExtensionNames.forEach(function (loadedExtensionName) {
svgCanvas.runExtension(loadedExtensionName, 'langReady',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */
@ -36096,7 +36201,7 @@ editor.init = function () {
});
});
case 18:
case 19:
svgCanvas.runExtensions('langChanged',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */
lang); // Update flyout tooltips
@ -36117,7 +36222,7 @@ editor.init = function () {
$$b('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
case 23:
case 24:
case "end":
return _context17.stop();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

195
dist/index-umd.js vendored
View File

@ -9632,6 +9632,10 @@
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -9664,7 +9668,7 @@
});
} else if (type === 'select') {
var div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $("<select aria-label=\"".concat(msg, "\">")).appendTo(div);
if (checkbox) {
var label = $('<label>').text(checkbox.label);
@ -22310,11 +22314,17 @@
var svgIcons = {};
var fixIDs;
/**
* List of raster images with each
* key being the SVG icon ID to replace, and the value the image file name
* Map of raster images with each key being the SVG icon ID
* to replace, and the value the image file name
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
*/
/**
* Map of raster images with each key being the SVG icon ID
* whose `alt` will be set, and the value being the `alt` text
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Alts
*/
/**
* @function external:jQuery.svgIcons
* @param {string} file The location of a local SVG or SVGz file
@ -22323,21 +22333,29 @@
* @param {Float} [opts.h] The icon heights
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
* @param {string} [opts.fallback_path] The path to use for all images
listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids
as values. This provides a custom method of adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with
corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>`
element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to
parse as XML. SVGZ files add compression benefits, but getting data from
them fails in Firefox 2 and older.
* listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will
* be replaced by, rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] Map with selectors
* for keys and SVG icon ids as values. This provides a custom method of
* adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] Map
* with selectors for keys and numbers as values. This allows an easy way to
* resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A
* function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match
* SVG icon ids with corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon
* into an `<img>` element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and
* thus not to parse as XML. SVGZ files add compression benefits, but
* getting data from them fails in Firefox 2 and older.
* @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key
* being the SVG icon ID whose `alt` will be set, and the value being
* the `alt` text
* @param {string} [opts.testIconAlt="icon"] Alt text for the injected test image.
* In case wish to ensure have one for accessibility
* @returns {undefined}
*/
@ -22448,7 +22466,8 @@
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
height: 0,
alt: opts.testIconAlt || 'icon'
}).appendTo('body').load(function () {
// Safari 4 crashes, Opera and Chrome don't
makeIcons(true);
@ -22466,7 +22485,7 @@
* @param {external:jQuery} target
* @param {external:jQuery} icon A wrapped `defs` or Image
* @param {string} id SVG icon ID
* @param {string} setID
* @param {boolean} setID Whether to set the ID attribute (with `id`)
* @returns {undefined}
*/
@ -22478,6 +22497,17 @@
if (setID) icon.attr('id', id);
var cl = target.attr('class');
if (cl) icon.attr('class', 'svg_icon ' + cl);
if (!target.alt) {
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon.attr('alt', alt);
}
target.replaceWith(icon);
} else {
target.append(icon);
@ -22528,12 +22558,18 @@
var path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
var icon = $(new Image()).attr({
class: 'svg_icon',
src: path + imgsrc,
width: iconW,
height: iconH,
alt: 'icon'
alt: alt
});
addIcon(icon, id);
});
@ -22576,9 +22612,16 @@
if (toImage) {
tempHolder.empty().append(svgroot);
var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon = $(new Image()).attr({
class: 'svg_icon',
src: str
src: str,
alt: alt
});
} else {
icon = fixIDs($(svgroot), i);
@ -22711,13 +22754,15 @@
*/
/**
* If a Float is used, it will represent width and height. Arrays contain the width and height.
* If a Float is used, it will represent width and height. Arrays contain
* the width and height.
* @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size
*/
/**
* @function external:jQuery.resizeSvgIcons
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with
* selectors as keys. The values are sizes.
* @returns {undefined}
*/
@ -28029,8 +28074,22 @@
var $$a = jQuery;
var langParam;
/**
* Looks for elements to localize using the supplied `obj` to indicate
* on which selectors (or IDs if `ids` is set to `true`) to set its
* strings (with selectors relative to the editor root element). All
* keys will be translated, but for each selector, only the first item
* found matching will be modified.
* If the type is `content`, the selector-identified element's children
* will be checked, and the first (non-empty) text (placeholder) node
* found will have its text replaced.
* If the type is `title`, the element's `title`
* property will be set.
* If the type is `aria-label`, the element's `aria-label` attribute
* will be set (i.e., instructions for screen readers when there is
* otherwise no visible text to be read for the function of the form
* control).
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj
* @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings
* @param {boolean} ids
* @returns {undefined}
*/
@ -28054,12 +28113,18 @@
var $elem = parent.find(sel);
if ($elem.length) {
var elem = parent.find(sel)[0];
var elem = $elem[0];
switch (type) {
case 'aria-label':
elem.setAttribute('aria-label', val);
break;
case 'content':
_toConsumableArray(elem.childNodes).some(function (node) {
if (node.nodeType === 3 && node.textContent.trim()) {
if (node.nodeType === 3
/* Node.TEXT_NODE */
&& node.textContent.trim()) {
node.textContent = val;
return true;
}
@ -28097,6 +28162,7 @@
var editor_;
/**
* Sets the current editor instance (on which `addLangData`) exists.
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
@ -28125,7 +28191,7 @@
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(langData) {
var more, _langData, tools, properties, config, layers, common, ui, opts;
var more, _langData, tools, properties, config, layers, common, ui, opts, ariaLabels;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
@ -28152,6 +28218,7 @@
case 6:
_langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui;
setStrings('content', {
// Todo: Add this powered by (probably by default) but with config to remove
// copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html
curve_segments: properties.curve_segments,
fitToContent: tools.fitToContent,
@ -28209,14 +28276,41 @@
}, true); // Context menus
opts = {};
$$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () {
opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this];
['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'].forEach(function (item) {
opts['#cmenu_canvas a[href="#' + item + '"]'] = tools[item];
});
$$a.each(['dupe', 'merge_down', 'merge_all'], function () {
opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this];
['dupe', 'merge_down', 'merge_all'].forEach(function (item) {
opts['#cmenu_layers a[href="#' + item + '"]'] = layers[item];
});
opts['#cmenu_layers a[href="#delete"]'] = layers.del;
setStrings('content', opts);
ariaLabels = {};
Object.entries({
tool_blur: properties.blur,
tool_position: tools.align_to_page,
tool_font_family: properties.font_family,
zoom_panel: ui.zoom_level,
stroke_linejoin: properties.linejoin_miter,
stroke_linecap: properties.linecap_butt,
tool_opacity: properties.opacity
}).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
id = _ref5[0],
value = _ref5[1];
ariaLabels['#' + id + ' button'] = value;
});
Object.entries({
group_opacity: properties.opacity,
zoom: ui.zoom_level
}).forEach(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
id = _ref7[0],
value = _ref7[1];
ariaLabels['#' + id] = value;
});
setStrings('aria-label', ariaLabels);
setStrings('title', {
align_relative_to: tools.align_relative_to,
circle_cx: properties.circle_cx,
@ -28320,7 +28414,7 @@
langData: langData
});
case 15:
case 19:
case "end":
return _context.stop();
}
@ -28333,6 +28427,7 @@
};
}();
/**
*
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
@ -28346,7 +28441,7 @@
var putLocale =
/*#__PURE__*/
function () {
var _ref4 = _asyncToGenerator(
var _ref8 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) {
var url;
@ -28402,7 +28497,7 @@
}));
return function putLocale(_x2, _x3, _x4) {
return _ref4.apply(this, arguments);
return _ref8.apply(this, arguments);
};
}();
@ -29887,6 +29982,8 @@
no_img: !isWebkit(),
// Opera & Firefox 4 gives odd behavior w/images
fallback_path: curConfig.imgPath,
// Todo: Set `alts: {}` with keys as the IDs in fallback set to
// `uiStrings` (localized) values
fallback: {
logo: 'logo.png',
select: 'select.png',
@ -31902,7 +31999,7 @@
var _ref13 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee5(win, ext) {
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders;
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, altsObj, placementObj, holders;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
@ -32092,7 +32189,7 @@
break;
}
fallbackObj = {}, placementObj = {}, holders = {};
fallbackObj = {}, altsObj = {}, placementObj = {}, holders = {};
/**
* @typedef {GenericArray} module:SVGEditor.KeyArray
* @property {string} 0 The key to bind (on `keydown`)
@ -32137,9 +32234,10 @@
var icon;
if (!svgicons) {
icon = $$b('<img src="' + btn.icon + '">');
icon = $$b('<img src="' + btn.icon + (btn.title ? '" alt="' + btn.title : '') + '">');
} else {
fallbackObj[id] = btn.icon;
altsObj[id] = btn.title;
var svgicon = btn.svgicon || btn.id;
if (btn.type === 'app_menu') {
@ -36051,6 +36149,13 @@
return _context17.abrupt("return");
case 5:
// Todo: Remove `allStrings.lang` property in locale in
// favor of just `lang`?
document.documentElement.lang = allStrings.lang; // lang;
// Todo: Add proper RTL Support!
// Todo: Use RTL detection instead and take out of locales?
// document.documentElement.dir = allStrings.dir;
$$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
@ -36066,11 +36171,11 @@
if (!extsPreLang.length) {
_context17.next = 17;
_context17.next = 18;
break;
}
_context17.next = 14;
_context17.next = 15;
return Promise.all(extsPreLang.map(function (ext) {
loadedExtensionNames.push(ext.name);
return ext.langReady({
@ -36083,12 +36188,12 @@
});
}));
case 14:
case 15:
extsPreLang.length = 0;
_context17.next = 18;
_context17.next = 19;
break;
case 17:
case 18:
loadedExtensionNames.forEach(function (loadedExtensionName) {
svgCanvas.runExtension(loadedExtensionName, 'langReady',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */
@ -36102,7 +36207,7 @@
});
});
case 18:
case 19:
svgCanvas.runExtensions('langChanged',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */
lang); // Update flyout tooltips
@ -36123,7 +36228,7 @@
$$b('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
case 23:
case 24:
case "end":
return _context17.stop();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2661,6 +2661,10 @@ var SvgCanvas = (function () {
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -2693,7 +2697,7 @@ var SvgCanvas = (function () {
});
} else if (type === 'select') {
var div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $("<select aria-label=\"".concat(msg, "\">")).appendTo(div);
if (checkbox) {
var label = $('<label>').text(checkbox.label);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,10 +28,16 @@ to use less-distracting single quotes if not
## Special properties
The `lang` property should define its HTML `lang` value (which should
probably always be the same as "<lang>" within the "lang.<lang>.js"
file name). This is important for accessibility (screen readers),
search engines, and, for some languages, font selection (e.g., Chinese,
Japanese and Korean languages are expected in different font styles,
despite many characters being shared). `lang` can also potentially be
used programmatically for different styling or behaviors.
While not currently in use, the `dir` property should be used to indicate
the default directionality of the language of the locale, while the `lang`
should define its HTML `lang` value (which should probably always be the
same as "<lang>" within the "lang.<lang>.js" file name).
the default directionality of the language of the locale.
## Location of locale files (including for extensions)

View File

@ -49,6 +49,10 @@ export default function jQueryPluginDBox ($, strings = {ok: 'Ok', cancel: 'Cance
* @returns {undefined}
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -81,7 +85,7 @@ export default function jQueryPluginDBox ($, strings = {ok: 'Ok', cancel: 'Cance
ctrl.bind('keydown', 'return', function () { ok.click(); });
} else if (type === 'select') {
const div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $(`<select aria-label="${msg}">`).appendTo(div);
if (checkbox) {
const label = $('<label>').text(checkbox.label);
chkbx = $('<input type="checkbox">').appendTo(label);

View File

@ -1,3 +1,4 @@
export default {
saved: 'Saved! Return to Item View!'
saved: 'Saved! Return to Item View!',
hiddenframe: 'Moinsave frame to store hidden values'
};

View File

@ -0,0 +1,4 @@
export default {
uploading: 'Uploading...',
hiddenframe: 'Opensave frame to store hidden values'
};

View File

@ -0,0 +1,4 @@
export default {
uploading: '正在上传...',
hiddenframe: 'Opensave frame to store hidden values'
};

View File

@ -1,3 +1,4 @@
export default {
saved: '已保存! 返回视图!'
saved: '已保存! 返回视图!',
hiddenframe: 'Moinsave frame to store hidden values'
};

View File

@ -1,3 +0,0 @@
export default {
uploading: 'Uploading...'
};

View File

@ -1,3 +0,0 @@
export default {
uploading: '正在上传...'
};

View File

@ -20,7 +20,10 @@ export default {
// Create upload target (hidden iframe)
// Hiding by size instead of display to avoid FF console errors
// with `getBBox` in browser.js `supportsPathBBox_`)
/* const target = */ $('<iframe name="output_frame" style="width: 0; height: 0;" src="#"/>').appendTo('body');
/* const target = */ $(
`<iframe name="output_frame" title="${strings.hiddenframe}"
style="width: 0; height: 0;" src="#"/>`
).appendTo('body');
svgEditor.setCustomHandlers({
async save (win, data) {

View File

@ -61,7 +61,10 @@ export default {
// Hiding by size instead of display to avoid FF console errors
// with `getBBox` in browser.js `supportsPathBBox_`)
$('<iframe name="output_frame" style="width: 0; height: 0;" src="#"/>').appendTo('body');
$(
`<iframe name="output_frame" title="${strings.hiddenframe}"
style="width: 0; height: 0;" src="#"/>`
).appendTo('body');
svgEditor.setCustomHandlers({
save (win, data) {
const svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, // Firefox doesn't seem to know it is UTF-8 (no matter whether we use or skip the clientDownload code) despite the Content-Disposition header containing UTF-8, but adding the encoding works

View File

@ -31,10 +31,24 @@ const $ = jQuery;
let langParam;
/**
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj
* @param {boolean} ids
* @returns {undefined}
* Looks for elements to localize using the supplied `obj` to indicate
* on which selectors (or IDs if `ids` is set to `true`) to set its
* strings (with selectors relative to the editor root element). All
* keys will be translated, but for each selector, only the first item
* found matching will be modified.
* If the type is `content`, the selector-identified element's children
* will be checked, and the first (non-empty) text (placeholder) node
* found will have its text replaced.
* If the type is `title`, the element's `title`
* property will be set.
* If the type is `aria-label`, the element's `aria-label` attribute
* will be set (i.e., instructions for screen readers when there is
* otherwise no visible text to be read for the function of the form
* control).
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings
* @param {boolean} ids
* @returns {undefined}
*/
export const setStrings = function (type, obj, ids) {
// Root element to look for element from
@ -47,12 +61,17 @@ export const setStrings = function (type, obj, ids) {
if (ids) { sel = '#' + sel; }
const $elem = parent.find(sel);
if ($elem.length) {
const elem = parent.find(sel)[0];
const elem = $elem[0];
switch (type) {
case 'aria-label':
elem.setAttribute('aria-label', val);
break;
case 'content':
[...elem.childNodes].some((node) => {
if (node.nodeType === 3 && node.textContent.trim()) {
if (node.nodeType === 3 /* Node.TEXT_NODE */ &&
node.textContent.trim()
) {
node.textContent = val;
return true;
}
@ -88,10 +107,11 @@ export const setStrings = function (type, obj, ids) {
let editor_;
/**
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
* @returns {undefined}
* Sets the current editor instance (on which `addLangData`) exists.
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
* @returns {undefined}
*/
export const init = (editor) => {
editor_ = editor;
@ -127,6 +147,7 @@ export const readLang = async function (langData) {
} = langData;
setStrings('content', {
// Todo: Add this powered by (probably by default) but with config to remove
// copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html
curve_segments: properties.curve_segments,
fitToContent: tools.fitToContent,
@ -197,18 +218,42 @@ export const readLang = async function (langData) {
// Context menus
const opts = {};
$.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () {
opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this];
[
'cut', 'copy', 'paste', 'paste_in_place', 'delete',
'group', 'ungroup', 'move_front', 'move_up',
'move_down', 'move_back'
].forEach((item) => {
opts['#cmenu_canvas a[href="#' + item + '"]'] = tools[item];
});
$.each(['dupe', 'merge_down', 'merge_all'], function () {
opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this];
['dupe', 'merge_down', 'merge_all'].forEach((item) => {
opts['#cmenu_layers a[href="#' + item + '"]'] = layers[item];
});
opts['#cmenu_layers a[href="#delete"]'] = layers.del;
setStrings('content', opts);
const ariaLabels = {};
Object.entries({
tool_blur: properties.blur,
tool_position: tools.align_to_page,
tool_font_family: properties.font_family,
zoom_panel: ui.zoom_level,
stroke_linejoin: properties.linejoin_miter,
stroke_linecap: properties.linecap_butt,
tool_opacity: properties.opacity
}).forEach(([id, value]) => {
ariaLabels['#' + id + ' button'] = value;
});
Object.entries({
group_opacity: properties.opacity,
zoom: ui.zoom_level
}).forEach(([id, value]) => {
ariaLabels['#' + id] = value;
});
setStrings('aria-label', ariaLabels);
setStrings('title', {
align_relative_to: tools.align_relative_to,
circle_cx: properties.circle_cx,
@ -313,14 +358,15 @@ export const readLang = async function (langData) {
};
/**
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
* @param {{langPath: string}} conf
* @fires module:svgcanvas.SvgCanvas#event:ext-addLangData
* @fires module:svgcanvas.SvgCanvas#event:ext-langReady
* @fires module:svgcanvas.SvgCanvas#event:ext-langChanged
* @returns {Promise} Resolves to result of {@link module:locale.readLang}
*
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
* @param {{langPath: string}} conf
* @fires module:svgcanvas.SvgCanvas#event:ext-addLangData
* @fires module:svgcanvas.SvgCanvas#event:ext-langReady
* @fires module:svgcanvas.SvgCanvas#event:ext-langChanged
* @returns {Promise} Resolves to result of {@link module:locale.readLang}
*/
export const putLocale = async function (givenParam, goodLangs, conf) {
if (givenParam) {

View File

@ -43,7 +43,7 @@
<body>
<div id="svg_container" style="visibility: hidden;">
<div id="svg_editor">
<div id="svg_editor" role="main">
<div id="rulers">
<div id="ruler_corner"></div>
<div id="ruler_x">

View File

@ -44,7 +44,7 @@
<body>
<div id="svg_container" style="visibility: hidden;">
<div id="svg_editor">
<div id="svg_editor" role="main">
<div id="rulers">
<div id="ruler_corner"></div>
<div id="ruler_x">

View File

@ -1175,6 +1175,8 @@ editor.init = function () {
id_match: false,
no_img: !isWebkit(), // Opera & Firefox 4 gives odd behavior w/images
fallback_path: curConfig.imgPath,
// Todo: Set `alts: {}` with keys as the IDs in fallback set to
// `uiStrings` (localized) values
fallback: {
logo: 'logo.png',
@ -2149,7 +2151,10 @@ editor.init = function () {
const bNoFill = (svgCanvas.getColor('fill') === 'none');
const bNoStroke = (svgCanvas.getColor('stroke') === 'none');
const buttonsNeedingStroke = ['#tool_fhpath', '#tool_line'];
const buttonsNeedingFillAndStroke = ['#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_path'];
const buttonsNeedingFillAndStroke = [
'#tools_rect .tool_button', '#tools_ellipse .tool_button',
'#tool_text', '#tool_path'
];
if (bNoStroke) {
buttonsNeedingStroke.forEach((btn) => {
@ -2177,10 +2182,13 @@ editor.init = function () {
});
}
svgCanvas.runExtensions('toolButtonStateUpdate', /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */ {
svgCanvas.runExtensions(
'toolButtonStateUpdate',
/** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */ {
nofill: bNoFill,
nostroke: bNoStroke
});
}
);
// Disable flyouts if all inside are disabled
$('.tools_flyout').each(function () {
@ -3194,6 +3202,7 @@ editor.init = function () {
const {svgicons} = ext;
if (ext.buttons) {
const fallbackObj = {},
altsObj = {},
placementObj = {},
holders = {};
@ -3235,9 +3244,14 @@ editor.init = function () {
let icon;
if (!svgicons) {
icon = $('<img src="' + btn.icon + '">');
icon = $(
'<img src="' + btn.icon +
(btn.title ? '" alt="' + btn.title : '') +
'">'
);
} else {
fallbackObj[id] = btn.icon;
altsObj[id] = btn.title;
const svgicon = btn.svgicon || btn.id;
if (btn.type === 'app_menu') {
placementObj['#' + id + ' > div'] = svgicon;
@ -4931,7 +4945,11 @@ editor.init = function () {
// 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 toolnames = [
'clear', 'open', 'save', 'source', 'delete',
'delete_multi', 'paste', 'clone', 'clone_multi',
'move_top', 'move_bottom'
];
const curClass = 'tool_button_current';
let allTools = '';
@ -4967,7 +4985,11 @@ editor.init = function () {
if (button) {
const {title} = button;
const index = title.indexOf('Ctrl+');
button.title = [title.substr(0, index), 'Cmd+', title.substr(index + 5)].join('');
button.title = [
title.substr(0, index),
'Cmd+',
title.substr(index + 5)
].join('');
}
}
}
@ -6200,6 +6222,12 @@ editor.init = function () {
if (!allStrings) {
return;
}
// Todo: Remove `allStrings.lang` property in locale in
// favor of just `lang`?
document.documentElement.lang = allStrings.lang; // lang;
// Todo: Add proper RTL Support!
// Todo: Use RTL detection instead and take out of locales?
// document.documentElement.dir = allStrings.dir;
$.extend(uiStrings, allStrings);
// const notif = allStrings.notification; // Currently unused

View File

@ -103,10 +103,15 @@ export default function jQueryPluginSVGIcons ($) {
let fixIDs;
/**
* List of raster images with each
* key being the SVG icon ID to replace, and the value the image file name
* Map of raster images with each key being the SVG icon ID
* to replace, and the value the image file name
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
*/
/**
* Map of raster images with each key being the SVG icon ID
* whose `alt` will be set, and the value being the `alt` text
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Alts
*/
/**
* @function external:jQuery.svgIcons
* @param {string} file The location of a local SVG or SVGz file
@ -115,21 +120,29 @@ export default function jQueryPluginSVGIcons ($) {
* @param {Float} [opts.h] The icon heights
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
* @param {string} [opts.fallback_path] The path to use for all images
listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids
as values. This provides a custom method of adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with
corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>`
element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to
parse as XML. SVGZ files add compression benefits, but getting data from
them fails in Firefox 2 and older.
* listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will
* be replaced by, rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] Map with selectors
* for keys and SVG icon ids as values. This provides a custom method of
* adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] Map
* with selectors for keys and numbers as values. This allows an easy way to
* resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A
* function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match
* SVG icon ids with corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon
* into an `<img>` element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and
* thus not to parse as XML. SVGZ files add compression benefits, but
* getting data from them fails in Firefox 2 and older.
* @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key
* being the SVG icon ID whose `alt` will be set, and the value being
* the `alt` text
* @param {string} [opts.testIconAlt="icon"] Alt text for the injected test image.
* In case wish to ensure have one for accessibility
* @returns {undefined}
*/
$.svgIcons = function (file, opts = {}) {
@ -228,7 +241,8 @@ export default function jQueryPluginSVGIcons ($) {
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
height: 0,
alt: opts.testIconAlt || 'icon'
}).appendTo('body')
.load(function () {
// Safari 4 crashes, Opera and Chrome don't
@ -248,7 +262,7 @@ export default function jQueryPluginSVGIcons ($) {
* @param {external:jQuery} target
* @param {external:jQuery} icon A wrapped `defs` or Image
* @param {string} id SVG icon ID
* @param {string} setID
* @param {boolean} setID Whether to set the ID attribute (with `id`)
* @returns {undefined}
*/
function setIcon (target, icon, id, setID) {
@ -257,6 +271,13 @@ export default function jQueryPluginSVGIcons ($) {
if (setID) icon.attr('id', id);
const cl = target.attr('class');
if (cl) icon.attr('class', 'svg_icon ' + cl);
if (!target.alt) {
let alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon.attr('alt', alt);
}
target.replaceWith(icon);
} else {
target.append(icon);
@ -300,13 +321,17 @@ export default function jQueryPluginSVGIcons ($) {
const path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
let alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
const icon = $(new Image())
.attr({
class: 'svg_icon',
src: path + imgsrc,
width: iconW,
height: iconH,
alt: 'icon'
alt
});
addIcon(icon, id);
@ -352,9 +377,15 @@ export default function jQueryPluginSVGIcons ($) {
let icon;
if (toImage) {
tempHolder.empty().append(svgroot);
const str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
const str = dataPre + encode64(unescape(encodeURIComponent(
new XMLSerializer().serializeToString(svgroot)
)));
let alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon = $(new Image())
.attr({class: 'svg_icon', src: str});
.attr({class: 'svg_icon', src: str, alt});
} else {
icon = fixIDs($(svgroot), i);
}
@ -479,13 +510,15 @@ export default function jQueryPluginSVGIcons ($) {
*/
/**
* If a Float is used, it will represent width and height. Arrays contain the width and height.
* If a Float is used, it will represent width and height. Arrays contain
* the width and height.
* @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size
*/
/**
* @function external:jQuery.resizeSvgIcons
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with
* selectors as keys. The values are sizes.
* @returns {undefined}
*/
$.resizeSvgIcons = function (obj) {

View File

@ -44,7 +44,7 @@
<body>
<div id="svg_container" style="visibility: hidden;">
<div id="svg_editor">
<div id="svg_editor" role="main">
<div id="rulers">
<div id="ruler_corner"></div>
<div id="ruler_x">

View File

@ -44,7 +44,7 @@
<body>
<div id="svg_container" style="visibility: hidden;">
<div id="svg_editor">
<div id="svg_editor" role="main">
<div id="rulers">
<div id="ruler_corner"></div>
<div id="ruler_x">

View File

@ -9629,6 +9629,10 @@
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -9661,7 +9665,7 @@
});
} else if (type === 'select') {
var div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $("<select aria-label=\"".concat(msg, "\">")).appendTo(div);
if (checkbox) {
var label = $('<label>').text(checkbox.label);
@ -22307,11 +22311,17 @@
var svgIcons = {};
var fixIDs;
/**
* List of raster images with each
* key being the SVG icon ID to replace, and the value the image file name
* Map of raster images with each key being the SVG icon ID
* to replace, and the value the image file name
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
*/
/**
* Map of raster images with each key being the SVG icon ID
* whose `alt` will be set, and the value being the `alt` text
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Alts
*/
/**
* @function external:jQuery.svgIcons
* @param {string} file The location of a local SVG or SVGz file
@ -22320,21 +22330,29 @@
* @param {Float} [opts.h] The icon heights
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
* @param {string} [opts.fallback_path] The path to use for all images
listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids
as values. This provides a custom method of adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with
corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>`
element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to
parse as XML. SVGZ files add compression benefits, but getting data from
them fails in Firefox 2 and older.
* listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will
* be replaced by, rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] Map with selectors
* for keys and SVG icon ids as values. This provides a custom method of
* adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] Map
* with selectors for keys and numbers as values. This allows an easy way to
* resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A
* function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match
* SVG icon ids with corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon
* into an `<img>` element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and
* thus not to parse as XML. SVGZ files add compression benefits, but
* getting data from them fails in Firefox 2 and older.
* @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key
* being the SVG icon ID whose `alt` will be set, and the value being
* the `alt` text
* @param {string} [opts.testIconAlt="icon"] Alt text for the injected test image.
* In case wish to ensure have one for accessibility
* @returns {undefined}
*/
@ -22445,7 +22463,8 @@
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
height: 0,
alt: opts.testIconAlt || 'icon'
}).appendTo('body').load(function () {
// Safari 4 crashes, Opera and Chrome don't
makeIcons(true);
@ -22463,7 +22482,7 @@
* @param {external:jQuery} target
* @param {external:jQuery} icon A wrapped `defs` or Image
* @param {string} id SVG icon ID
* @param {string} setID
* @param {boolean} setID Whether to set the ID attribute (with `id`)
* @returns {undefined}
*/
@ -22475,6 +22494,17 @@
if (setID) icon.attr('id', id);
var cl = target.attr('class');
if (cl) icon.attr('class', 'svg_icon ' + cl);
if (!target.alt) {
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon.attr('alt', alt);
}
target.replaceWith(icon);
} else {
target.append(icon);
@ -22525,12 +22555,18 @@
var path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
var icon = $(new Image()).attr({
class: 'svg_icon',
src: path + imgsrc,
width: iconW,
height: iconH,
alt: 'icon'
alt: alt
});
addIcon(icon, id);
});
@ -22573,9 +22609,16 @@
if (toImage) {
tempHolder.empty().append(svgroot);
var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon = $(new Image()).attr({
class: 'svg_icon',
src: str
src: str,
alt: alt
});
} else {
icon = fixIDs($(svgroot), i);
@ -22708,13 +22751,15 @@
*/
/**
* If a Float is used, it will represent width and height. Arrays contain the width and height.
* If a Float is used, it will represent width and height. Arrays contain
* the width and height.
* @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size
*/
/**
* @function external:jQuery.resizeSvgIcons
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with
* selectors as keys. The values are sizes.
* @returns {undefined}
*/
@ -28026,8 +28071,22 @@
var $$a = jQuery;
var langParam;
/**
* Looks for elements to localize using the supplied `obj` to indicate
* on which selectors (or IDs if `ids` is set to `true`) to set its
* strings (with selectors relative to the editor root element). All
* keys will be translated, but for each selector, only the first item
* found matching will be modified.
* If the type is `content`, the selector-identified element's children
* will be checked, and the first (non-empty) text (placeholder) node
* found will have its text replaced.
* If the type is `title`, the element's `title`
* property will be set.
* If the type is `aria-label`, the element's `aria-label` attribute
* will be set (i.e., instructions for screen readers when there is
* otherwise no visible text to be read for the function of the form
* control).
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj
* @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings
* @param {boolean} ids
* @returns {undefined}
*/
@ -28051,12 +28110,18 @@
var $elem = parent.find(sel);
if ($elem.length) {
var elem = parent.find(sel)[0];
var elem = $elem[0];
switch (type) {
case 'aria-label':
elem.setAttribute('aria-label', val);
break;
case 'content':
_toConsumableArray(elem.childNodes).some(function (node) {
if (node.nodeType === 3 && node.textContent.trim()) {
if (node.nodeType === 3
/* Node.TEXT_NODE */
&& node.textContent.trim()) {
node.textContent = val;
return true;
}
@ -28094,6 +28159,7 @@
var editor_;
/**
* Sets the current editor instance (on which `addLangData`) exists.
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
@ -28122,7 +28188,7 @@
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(langData) {
var more, _langData, tools, properties, config, layers, common, ui, opts;
var more, _langData, tools, properties, config, layers, common, ui, opts, ariaLabels;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
@ -28149,6 +28215,7 @@
case 6:
_langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui;
setStrings('content', {
// Todo: Add this powered by (probably by default) but with config to remove
// copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html
curve_segments: properties.curve_segments,
fitToContent: tools.fitToContent,
@ -28206,14 +28273,41 @@
}, true); // Context menus
opts = {};
$$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () {
opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this];
['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'].forEach(function (item) {
opts['#cmenu_canvas a[href="#' + item + '"]'] = tools[item];
});
$$a.each(['dupe', 'merge_down', 'merge_all'], function () {
opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this];
['dupe', 'merge_down', 'merge_all'].forEach(function (item) {
opts['#cmenu_layers a[href="#' + item + '"]'] = layers[item];
});
opts['#cmenu_layers a[href="#delete"]'] = layers.del;
setStrings('content', opts);
ariaLabels = {};
Object.entries({
tool_blur: properties.blur,
tool_position: tools.align_to_page,
tool_font_family: properties.font_family,
zoom_panel: ui.zoom_level,
stroke_linejoin: properties.linejoin_miter,
stroke_linecap: properties.linecap_butt,
tool_opacity: properties.opacity
}).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
id = _ref5[0],
value = _ref5[1];
ariaLabels['#' + id + ' button'] = value;
});
Object.entries({
group_opacity: properties.opacity,
zoom: ui.zoom_level
}).forEach(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
id = _ref7[0],
value = _ref7[1];
ariaLabels['#' + id] = value;
});
setStrings('aria-label', ariaLabels);
setStrings('title', {
align_relative_to: tools.align_relative_to,
circle_cx: properties.circle_cx,
@ -28317,7 +28411,7 @@
langData: langData
});
case 15:
case 19:
case "end":
return _context.stop();
}
@ -28330,6 +28424,7 @@
};
}();
/**
*
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
@ -28343,7 +28438,7 @@
var putLocale =
/*#__PURE__*/
function () {
var _ref4 = _asyncToGenerator(
var _ref8 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) {
var url;
@ -28399,7 +28494,7 @@
}));
return function putLocale(_x2, _x3, _x4) {
return _ref4.apply(this, arguments);
return _ref8.apply(this, arguments);
};
}();
@ -29884,6 +29979,8 @@
no_img: !isWebkit(),
// Opera & Firefox 4 gives odd behavior w/images
fallback_path: curConfig.imgPath,
// Todo: Set `alts: {}` with keys as the IDs in fallback set to
// `uiStrings` (localized) values
fallback: {
logo: 'logo.png',
select: 'select.png',
@ -31899,7 +31996,7 @@
var _ref13 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee5(win, ext) {
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders;
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, altsObj, placementObj, holders;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
@ -32089,7 +32186,7 @@
break;
}
fallbackObj = {}, placementObj = {}, holders = {};
fallbackObj = {}, altsObj = {}, placementObj = {}, holders = {};
/**
* @typedef {GenericArray} module:SVGEditor.KeyArray
* @property {string} 0 The key to bind (on `keydown`)
@ -32134,9 +32231,10 @@
var icon;
if (!svgicons) {
icon = $$b('<img src="' + btn.icon + '">');
icon = $$b('<img src="' + btn.icon + (btn.title ? '" alt="' + btn.title : '') + '">');
} else {
fallbackObj[id] = btn.icon;
altsObj[id] = btn.title;
var svgicon = btn.svgicon || btn.id;
if (btn.type === 'app_menu') {
@ -36048,6 +36146,13 @@
return _context17.abrupt("return");
case 5:
// Todo: Remove `allStrings.lang` property in locale in
// favor of just `lang`?
document.documentElement.lang = allStrings.lang; // lang;
// Todo: Add proper RTL Support!
// Todo: Use RTL detection instead and take out of locales?
// document.documentElement.dir = allStrings.dir;
$$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
@ -36063,11 +36168,11 @@
if (!extsPreLang.length) {
_context17.next = 17;
_context17.next = 18;
break;
}
_context17.next = 14;
_context17.next = 15;
return Promise.all(extsPreLang.map(function (ext) {
loadedExtensionNames.push(ext.name);
return ext.langReady({
@ -36080,12 +36185,12 @@
});
}));
case 14:
case 15:
extsPreLang.length = 0;
_context17.next = 18;
_context17.next = 19;
break;
case 17:
case 18:
loadedExtensionNames.forEach(function (loadedExtensionName) {
svgCanvas.runExtension(loadedExtensionName, 'langReady',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */
@ -36099,7 +36204,7 @@
});
});
case 18:
case 19:
svgCanvas.runExtensions('langChanged',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */
lang); // Update flyout tooltips
@ -36120,7 +36225,7 @@
$$b('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
case 23:
case 24:
case "end":
return _context17.stop();
}

View File

@ -9629,6 +9629,10 @@
*/
/**
* Creates a dialog of the specified type with a given message
* and any defaults and type-specific metadata. Returns a `Promise`
* which resolves differently depending on whether the dialog
* was cancelled or okayed (with the response and any checked state).
* @param {"alert"|"prompt"|"select"|"process"} type
* @param {string} msg
* @param {string} [defaultVal]
@ -9661,7 +9665,7 @@
});
} else if (type === 'select') {
var div = $('<div style="text-align:center;">');
ctrl = $('<select>').appendTo(div);
ctrl = $("<select aria-label=\"".concat(msg, "\">")).appendTo(div);
if (checkbox) {
var label = $('<label>').text(checkbox.label);
@ -22307,11 +22311,17 @@
var svgIcons = {};
var fixIDs;
/**
* List of raster images with each
* key being the SVG icon ID to replace, and the value the image file name
* Map of raster images with each key being the SVG icon ID
* to replace, and the value the image file name
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
*/
/**
* Map of raster images with each key being the SVG icon ID
* whose `alt` will be set, and the value being the `alt` text
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Alts
*/
/**
* @function external:jQuery.svgIcons
* @param {string} file The location of a local SVG or SVGz file
@ -22320,21 +22330,29 @@
* @param {Float} [opts.h] The icon heights
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
* @param {string} [opts.fallback_path] The path to use for all images
listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] List with selectors for keys and SVG icon ids
as values. This provides a custom method of adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] List with selectors for keys and numbers
as values. This allows an easy way to resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match SVG icon ids with
corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon into an `<img>`
element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and thus not to
parse as XML. SVGZ files add compression benefits, but getting data from
them fails in Firefox 2 and older.
* listed under "fallback"
* @param {boolean} [opts.replace] If set to `true`, HTML elements will
* be replaced by, rather than include the SVG icon.
* @param {PlainObject.<string, string>} [opts.placement] Map with selectors
* for keys and SVG icon ids as values. This provides a custom method of
* adding icons.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} [opts.resize] Map
* with selectors for keys and numbers as values. This allows an easy way to
* resize specific icons.
* @param {module:jQuerySVGIcons.SVGIconsLoadedCallback} [opts.callback] A
* function to call when all icons have been loaded.
* @param {boolean} [opts.id_match=true] Automatically attempt to match
* SVG icon ids with corresponding HTML id
* @param {boolean} [opts.no_img] Prevent attempting to convert the icon
* into an `<img>` element (may be faster, help for browser consistency)
* @param {boolean} [opts.svgz] Indicate that the file is an SVGZ file, and
* thus not to parse as XML. SVGZ files add compression benefits, but
* getting data from them fails in Firefox 2 and older.
* @param {jQuery.svgIcons.Alts} [opts.alts] Map of images with each key
* being the SVG icon ID whose `alt` will be set, and the value being
* the `alt` text
* @param {string} [opts.testIconAlt="icon"] Alt text for the injected test image.
* In case wish to ensure have one for accessibility
* @returns {undefined}
*/
@ -22445,7 +22463,8 @@
testImg = $(new Image()).attr({
src: testSrc,
width: 0,
height: 0
height: 0,
alt: opts.testIconAlt || 'icon'
}).appendTo('body').load(function () {
// Safari 4 crashes, Opera and Chrome don't
makeIcons(true);
@ -22463,7 +22482,7 @@
* @param {external:jQuery} target
* @param {external:jQuery} icon A wrapped `defs` or Image
* @param {string} id SVG icon ID
* @param {string} setID
* @param {boolean} setID Whether to set the ID attribute (with `id`)
* @returns {undefined}
*/
@ -22475,6 +22494,17 @@
if (setID) icon.attr('id', id);
var cl = target.attr('class');
if (cl) icon.attr('class', 'svg_icon ' + cl);
if (!target.alt) {
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon.attr('alt', alt);
}
target.replaceWith(icon);
} else {
target.append(icon);
@ -22525,12 +22555,18 @@
var path = opts.fallback_path || '';
$.each(fallback, function (id, imgsrc) {
holder = $('#' + id);
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
var icon = $(new Image()).attr({
class: 'svg_icon',
src: path + imgsrc,
width: iconW,
height: iconH,
alt: 'icon'
alt: alt
});
addIcon(icon, id);
});
@ -22573,9 +22609,16 @@
if (toImage) {
tempHolder.empty().append(svgroot);
var str = dataPre + encode64(unescape(encodeURIComponent(new XMLSerializer().serializeToString(svgroot))));
var alt = 'icon';
if (opts.alts) {
alt = opts.alts[id] || alt;
}
icon = $(new Image()).attr({
class: 'svg_icon',
src: str
src: str,
alt: alt
});
} else {
icon = fixIDs($(svgroot), i);
@ -22708,13 +22751,15 @@
*/
/**
* If a Float is used, it will represent width and height. Arrays contain the width and height.
* If a Float is used, it will represent width and height. Arrays contain
* the width and height.
* @typedef {module:jQuerySVGIcons.Dimensions|Float} module:jQuerySVGIcons.Size
*/
/**
* @function external:jQuery.resizeSvgIcons
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with selectors as keys. The values are sizes.
* @param {PlainObject.<string, module:jQuerySVGIcons.Size>} obj Object with
* selectors as keys. The values are sizes.
* @returns {undefined}
*/
@ -28026,8 +28071,22 @@
var $$a = jQuery;
var langParam;
/**
* Looks for elements to localize using the supplied `obj` to indicate
* on which selectors (or IDs if `ids` is set to `true`) to set its
* strings (with selectors relative to the editor root element). All
* keys will be translated, but for each selector, only the first item
* found matching will be modified.
* If the type is `content`, the selector-identified element's children
* will be checked, and the first (non-empty) text (placeholder) node
* found will have its text replaced.
* If the type is `title`, the element's `title`
* property will be set.
* If the type is `aria-label`, the element's `aria-label` attribute
* will be set (i.e., instructions for screen readers when there is
* otherwise no visible text to be read for the function of the form
* control).
* @param {"content"|"title"} type
* @param {module:locale.LocaleSelectorValue} obj
* @param {module:locale.LocaleSelectorValue} obj Selectors or IDs keyed to strings
* @param {boolean} ids
* @returns {undefined}
*/
@ -28051,12 +28110,18 @@
var $elem = parent.find(sel);
if ($elem.length) {
var elem = parent.find(sel)[0];
var elem = $elem[0];
switch (type) {
case 'aria-label':
elem.setAttribute('aria-label', val);
break;
case 'content':
_toConsumableArray(elem.childNodes).some(function (node) {
if (node.nodeType === 3 && node.textContent.trim()) {
if (node.nodeType === 3
/* Node.TEXT_NODE */
&& node.textContent.trim()) {
node.textContent = val;
return true;
}
@ -28094,6 +28159,7 @@
var editor_;
/**
* Sets the current editor instance (on which `addLangData`) exists.
* @function init
* @memberof module:locale
* @param {module:locale.LocaleEditorInit} editor
@ -28122,7 +28188,7 @@
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(langData) {
var more, _langData, tools, properties, config, layers, common, ui, opts;
var more, _langData, tools, properties, config, layers, common, ui, opts, ariaLabels;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
@ -28149,6 +28215,7 @@
case 6:
_langData = langData, tools = _langData.tools, properties = _langData.properties, config = _langData.config, layers = _langData.layers, common = _langData.common, ui = _langData.ui;
setStrings('content', {
// Todo: Add this powered by (probably by default) but with config to remove
// copyrightLabel: misc.powered_by, // Currently commented out in svg-editor.html
curve_segments: properties.curve_segments,
fitToContent: tools.fitToContent,
@ -28206,14 +28273,41 @@
}, true); // Context menus
opts = {};
$$a.each(['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'], function () {
opts['#cmenu_canvas a[href="#' + this + '"]'] = tools[this];
['cut', 'copy', 'paste', 'paste_in_place', 'delete', 'group', 'ungroup', 'move_front', 'move_up', 'move_down', 'move_back'].forEach(function (item) {
opts['#cmenu_canvas a[href="#' + item + '"]'] = tools[item];
});
$$a.each(['dupe', 'merge_down', 'merge_all'], function () {
opts['#cmenu_layers a[href="#' + this + '"]'] = layers[this];
['dupe', 'merge_down', 'merge_all'].forEach(function (item) {
opts['#cmenu_layers a[href="#' + item + '"]'] = layers[item];
});
opts['#cmenu_layers a[href="#delete"]'] = layers.del;
setStrings('content', opts);
ariaLabels = {};
Object.entries({
tool_blur: properties.blur,
tool_position: tools.align_to_page,
tool_font_family: properties.font_family,
zoom_panel: ui.zoom_level,
stroke_linejoin: properties.linejoin_miter,
stroke_linecap: properties.linecap_butt,
tool_opacity: properties.opacity
}).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
id = _ref5[0],
value = _ref5[1];
ariaLabels['#' + id + ' button'] = value;
});
Object.entries({
group_opacity: properties.opacity,
zoom: ui.zoom_level
}).forEach(function (_ref6) {
var _ref7 = _slicedToArray(_ref6, 2),
id = _ref7[0],
value = _ref7[1];
ariaLabels['#' + id] = value;
});
setStrings('aria-label', ariaLabels);
setStrings('title', {
align_relative_to: tools.align_relative_to,
circle_cx: properties.circle_cx,
@ -28317,7 +28411,7 @@
langData: langData
});
case 15:
case 19:
case "end":
return _context.stop();
}
@ -28330,6 +28424,7 @@
};
}();
/**
*
* @function module:locale.putLocale
* @param {string} givenParam
* @param {string[]} goodLangs
@ -28343,7 +28438,7 @@
var putLocale =
/*#__PURE__*/
function () {
var _ref4 = _asyncToGenerator(
var _ref8 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2(givenParam, goodLangs, conf) {
var url;
@ -28399,7 +28494,7 @@
}));
return function putLocale(_x2, _x3, _x4) {
return _ref4.apply(this, arguments);
return _ref8.apply(this, arguments);
};
}();
@ -29884,6 +29979,8 @@
no_img: !isWebkit(),
// Opera & Firefox 4 gives odd behavior w/images
fallback_path: curConfig.imgPath,
// Todo: Set `alts: {}` with keys as the IDs in fallback set to
// `uiStrings` (localized) values
fallback: {
logo: 'logo.png',
select: 'select.png',
@ -31899,7 +31996,7 @@
var _ref13 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee5(win, ext) {
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, placementObj, holders;
var cbCalled, resizeDone, lang, prepResize, runCallback, btnSelects, svgicons, fallbackObj, altsObj, placementObj, holders;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
@ -32089,7 +32186,7 @@
break;
}
fallbackObj = {}, placementObj = {}, holders = {};
fallbackObj = {}, altsObj = {}, placementObj = {}, holders = {};
/**
* @typedef {GenericArray} module:SVGEditor.KeyArray
* @property {string} 0 The key to bind (on `keydown`)
@ -32134,9 +32231,10 @@
var icon;
if (!svgicons) {
icon = $$b('<img src="' + btn.icon + '">');
icon = $$b('<img src="' + btn.icon + (btn.title ? '" alt="' + btn.title : '') + '">');
} else {
fallbackObj[id] = btn.icon;
altsObj[id] = btn.title;
var svgicon = btn.svgicon || btn.id;
if (btn.type === 'app_menu') {
@ -36048,6 +36146,13 @@
return _context17.abrupt("return");
case 5:
// Todo: Remove `allStrings.lang` property in locale in
// favor of just `lang`?
document.documentElement.lang = allStrings.lang; // lang;
// Todo: Add proper RTL Support!
// Todo: Use RTL detection instead and take out of locales?
// document.documentElement.dir = allStrings.dir;
$$b.extend(uiStrings$1, allStrings); // const notif = allStrings.notification; // Currently unused
// $.extend will only replace the given strings
@ -36063,11 +36168,11 @@
if (!extsPreLang.length) {
_context17.next = 17;
_context17.next = 18;
break;
}
_context17.next = 14;
_context17.next = 15;
return Promise.all(extsPreLang.map(function (ext) {
loadedExtensionNames.push(ext.name);
return ext.langReady({
@ -36080,12 +36185,12 @@
});
}));
case 14:
case 15:
extsPreLang.length = 0;
_context17.next = 18;
_context17.next = 19;
break;
case 17:
case 18:
loadedExtensionNames.forEach(function (loadedExtensionName) {
svgCanvas.runExtension(loadedExtensionName, 'langReady',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langReady} */
@ -36099,7 +36204,7 @@
});
});
case 18:
case 19:
svgCanvas.runExtensions('langChanged',
/** @type {module:svgcanvas.SvgCanvas#event:ext-langChanged} */
lang); // Update flyout tooltips
@ -36120,7 +36225,7 @@
$$b('#tool_pos' + this.id.substr(10))[0].title = this.title;
});
case 23:
case 24:
case "end":
return _context17.stop();
}

View File

@ -3,18 +3,40 @@
// https://github.com/helen-dikareva/axe-testcafe
import axeCheck from 'axe-testcafe';
/**
* @external TestcafeTest
*/
/**
* @param {external.TestcafeTest} t
* @returns {Promise}
*/
function axeCheckWithConfig (t) {
return axeCheck(
t,
// context: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#context-parameter
undefined,
// https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter
{
rules: {
'meta-viewport': {enabled: false}
}
}
// , (err, results) {} // https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#results-object
);
}
fixture`TestCafe Axe accessibility tests (Editor - no parameters)`
.page`http://localhost:8000/editor/svg-editor.html`;
test('Editor - no parameters', async (t) => {
await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
await axeCheckWithConfig(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
});
fixture`TestCafe Axe accessibility tests (Editor - with all extensions)`
.page`http://localhost:8000/editor/svg-editor.html?extensions=ext-arrows.js,ext-closepath.js,ext-foreignobject.js,ext-helloworld.js,ext-mathjax.js,ext-php_savefile.js,ext-server_moinsave.js,ext-server_opensave.js,ext-webappfind.js,ext-xdomain-messaging.js`;
test('Editor ES - with all extensions', async (t) => {
await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
test('Editor - with all extensions', async (t) => {
await axeCheckWithConfig(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
});
/* eslint-disable qunit/no-commented-tests */
@ -24,21 +46,21 @@ fixture`TestCafe Axe accessibility tests (Editor ES - no parameters)`
.page`http://localhost:8000/editor/svg-editor-es.html`;
test('Editor ES - no parameters', async t => {
await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
await axeCheckWithConfig(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
});
fixture`TestCafe Axe accessibility tests (Editor ES - with all extensions)`
.page`http://localhost:8000/editor/svg-editor-es.html?extensions=ext-arrows.js,ext-closepath.js,ext-foreignobject.js,ext-helloworld.js,ext-mathjax.js,ext-php_savefile.js,ext-server_moinsave.js,ext-server_opensave.js,ext-webappfind.js,ext-xdomain-messaging.js`;
test('Editor ES - with all extensions', async t => {
await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
await axeCheckWithConfig(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
});
fixture`TestCafe Axe accessibility tests (Embedded - no parameters)`
.page`http://localhost:8000/editor/embedapi.html`;
test('Embedded - no parameters', async t => {
await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
await axeCheckWithConfig(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
});
*/
/* eslint-enable qunit/no-commented-tests */