- Linting (ESLint): Stricter rules (or switch to warning)
- Breaking internal API change: `updateGripCursor` moved to be class method of Selector rather than instance method - Breaking internal API change: `subpathIsClosed` moved to be class method of `Path` rather than instance method - Refactoring: Reuse utilities base64 encoder for SVG icons plugin - Docs (JSDoc): Fix return of the `mouseUp` (can also be an object) and `mouseDown` (may also be a boolean) of `pathActions`; other JSDoc additions/improvementsmaster
parent
901c9547fe
commit
7c470e9909
314
.eslintrc
314
.eslintrc
|
@ -6,7 +6,7 @@
|
|||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["compat", "qunit", "testcafe", "jsdoc", "markdown"],
|
||||
"plugins": ["compat", "qunit", "testcafe", "jsdoc", "markdown", "import", "node", "promise"],
|
||||
"env": {
|
||||
"node": false,
|
||||
"browser": true
|
||||
|
@ -26,24 +26,296 @@
|
|||
"allowAugmentsExtendsWithoutParam": true
|
||||
}
|
||||
},
|
||||
"overrides": [{
|
||||
"files": ["**/*.md"],
|
||||
"rules": {
|
||||
"no-undef": ["off"],
|
||||
"no-unused-vars": ["warn"],
|
||||
"padded-blocks": ["off"]
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["editor/locale/lang.*.js"],
|
||||
"rules": {
|
||||
"import/no-anonymous-default-export": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["editor/extensions/ext-locale/**"],
|
||||
"rules": {
|
||||
"import/no-anonymous-default-export": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["editor/extensions/**/ext-*.js"],
|
||||
"rules": {
|
||||
"consistent-this": ["error", "svgEditor"],
|
||||
"import/no-anonymous-default-export": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"editor/svgpathseg.js", "editor/touch.js", "editor/typedefs.js",
|
||||
"editor/redirect-on-no-module-support.js",
|
||||
"test/all_tests.js", "screencasts/svgopen2010/script.js",
|
||||
"opera-widget/handlers.js",
|
||||
"firefox-extension/handlers.js",
|
||||
"firefox-extension/content/svg-edit-overlay.js"
|
||||
],
|
||||
"rules": {
|
||||
"import/unambiguous": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.md"],
|
||||
"rules": {
|
||||
"no-undef": ["off"],
|
||||
"no-unused-vars": ["warn"],
|
||||
"padded-blocks": ["off"],
|
||||
"import/unambiguous": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["test/**"],
|
||||
"rules": {
|
||||
"no-console": ["off"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"docs/jsdoc-config.js", "build-html.js", "jsdoc-check-overly-generic-types.js",
|
||||
"rollup.config.js", "rollup-config.config.js"
|
||||
],
|
||||
"rules": {
|
||||
"node/no-extraneous-import": ["error"],
|
||||
"node/no-extraneous-require": ["error"],
|
||||
"node/no-missing-import": ["error"],
|
||||
"node/no-missing-require": ["error"],
|
||||
"node/no-unpublished-bin": ["error"],
|
||||
"node/no-unpublished-import": ["error"],
|
||||
"node/no-unpublished-require": ["error"],
|
||||
"node/no-unsupported-features/es-builtins": ["error"],
|
||||
"node/no-unsupported-features/es-syntax": ["error"],
|
||||
"node/no-unsupported-features/node-builtins": ["error"],
|
||||
"node/process-exit-as-throw": ["error"],
|
||||
"node/shebang": ["error"],
|
||||
|
||||
"node/exports-style": ["error", "module.exports"],
|
||||
"node/prefer-global/buffer": ["error", "always"],
|
||||
"node/prefer-global/console": ["error", "always"],
|
||||
"node/prefer-global/process": ["error", "always"],
|
||||
"node/prefer-global/text-decoder": ["error", "always"],
|
||||
"node/prefer-global/text-encoder": ["error", "always"],
|
||||
"node/prefer-global/url-search-params": ["error", "always"],
|
||||
"node/prefer-global/url": ["error", "always"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["rollup.config.js", "rollup-config.config.js"],
|
||||
"rules": {
|
||||
"node/no-unsupported-features/es-syntax": "off",
|
||||
"node/no-unpublished-import": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["jsdoc-check-overly-generic-types.js", "build-html.js"],
|
||||
"rules": {
|
||||
"import/unambiguous": "off",
|
||||
"import/no-commonjs": "off"
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
"rules": {
|
||||
"semi": [2, "always"],
|
||||
"array-bracket-newline": ["error", "consistent"],
|
||||
"array-bracket-spacing": ["error"],
|
||||
"array-callback-return": ["error"],
|
||||
"array-element-newline": ["off"],
|
||||
"arrow-body-style": ["off"],
|
||||
"arrow-parens": ["error"],
|
||||
"block-scoped-var": ["error"],
|
||||
"callback-return": ["error"],
|
||||
"class-methods-use-this": ["warn"],
|
||||
"computed-property-spacing": ["error"],
|
||||
"consistent-return": ["error"],
|
||||
"consistent-this": ["warn"],
|
||||
"dot-notation": ["error"],
|
||||
"for-direction": ["error"],
|
||||
"func-name-matching": ["error"],
|
||||
"func-names": ["off"],
|
||||
"func-style": ["off"],
|
||||
"function-paren-newline": ["error", "consistent"],
|
||||
"getter-return": ["error"],
|
||||
"global-require": ["error"],
|
||||
"guard-for-in": ["error"],
|
||||
"id-blacklist": ["off"],
|
||||
"id-length": ["off"],
|
||||
"id-match": ["off"],
|
||||
"implicit-arrow-linebreak": ["error"],
|
||||
"init-declarations": ["off"],
|
||||
"jsx-quotes": ["error"],
|
||||
"line-comment-position": ["off"],
|
||||
"linebreak-style": ["error"],
|
||||
"lines-around-comment": ["off"],
|
||||
"lines-between-class-members": ["off"],
|
||||
"max-classes-per-file": ["off"],
|
||||
"max-depth": ["off"],
|
||||
"max-lines-per-function": ["off"],
|
||||
"max-lines": ["off"],
|
||||
"max-nested-callbacks": ["error"],
|
||||
"max-params": ["off"],
|
||||
"max-statements-per-line": ["off"],
|
||||
"max-statements": ["off"],
|
||||
"multiline-comment-style": ["off"],
|
||||
"multiline-ternary": ["error", "always-multiline"],
|
||||
"newline-after-var": ["off"],
|
||||
"newline-before-return": ["off"],
|
||||
"newline-per-chained-call": ["off"],
|
||||
"no-alert": ["warn"],
|
||||
"no-async-promise-executor": ["error"],
|
||||
"no-await-in-loop": ["error"],
|
||||
"no-bitwise": ["error"],
|
||||
"no-buffer-constructor": ["error"],
|
||||
"no-case-declarations": ["error"],
|
||||
"no-confusing-arrow": ["error"],
|
||||
"no-console": ["warn"],
|
||||
"no-continue": ["off"],
|
||||
"no-div-regex": ["error"],
|
||||
"no-duplicate-imports": ["error"],
|
||||
"no-else-return": ["error"],
|
||||
"no-empty-function": ["warn"],
|
||||
"no-empty": ["error", {"allowEmptyCatch": true}],
|
||||
"no-eq-null": ["error"],
|
||||
"no-extra-label": ["error"],
|
||||
"no-extra-semi": ["error"],
|
||||
"no-implicit-coercion": ["error"],
|
||||
"no-implicit-globals": ["error"],
|
||||
"no-inline-comments": ["off"],
|
||||
"no-invalid-this": ["off"],
|
||||
"no-lonely-if": ["error"],
|
||||
"no-loop-func": ["error"],
|
||||
"no-misleading-character-class": ["error"],
|
||||
"no-mixed-requires": ["error", {"grouping": true, "allowCall": true}],
|
||||
"no-multi-assign": ["off"],
|
||||
"no-negated-condition": ["off"],
|
||||
"no-nested-ternary": ["off"],
|
||||
"no-param-reassign": ["off"],
|
||||
"no-plusplus": ["off"],
|
||||
"no-process-env": ["error"],
|
||||
"no-process-exit": ["error"],
|
||||
"no-prototype-builtins": ["error"],
|
||||
"no-restricted-globals": ["error", {
|
||||
"name": "event",
|
||||
"message": "Use local event parameter instead (preferably as \"e\" or \"ev\")."
|
||||
}, {
|
||||
"name": "fdescribe",
|
||||
"message": "Do not commit fdescribe. Use describe instead."
|
||||
}],
|
||||
"no-restricted-imports": ["off"],
|
||||
"no-restricted-modules": ["off"],
|
||||
"no-restricted-properties": ["error", {
|
||||
"property": "__defineGetter__",
|
||||
"message": "Please use `Object.defineProperty` instead."
|
||||
}],
|
||||
"no-restricted-syntax": ["off"],
|
||||
"no-script-url": ["error"],
|
||||
"no-shadow": ["error", {"builtinGlobals": true, "hoist": "functions", "allow": ["parent", "top", "open", "name", "closed", "start"]}],
|
||||
"no-spaced-func": ["error"],
|
||||
"no-sync": ["error"],
|
||||
"no-ternary": ["off"],
|
||||
"no-undefined": ["off"],
|
||||
"no-underscore-dangle": ["off"],
|
||||
"no-unused-labels": ["error"],
|
||||
"no-useless-concat": ["off"],
|
||||
"no-var": ["error"],
|
||||
"no-void": ["error"],
|
||||
"nonblock-statement-body-position": ["error"],
|
||||
"object-curly-newline": ["off"],
|
||||
"object-shorthand": ["error", "always", {"avoidExplicitReturnArrows": true}],
|
||||
"one-var-declaration-per-line": ["off"],
|
||||
"operator-assignment": ["error"],
|
||||
"padding-line-between-statements": ["off"],
|
||||
"prefer-arrow-callback": ["off"],
|
||||
"prefer-const": ["error"],
|
||||
"prefer-destructuring": ["error", {"object": true}],
|
||||
"prefer-numeric-literals": ["warn"],
|
||||
"prefer-object-spread": ["error"],
|
||||
"prefer-rest-params": ["error"],
|
||||
"prefer-spread": ["error"],
|
||||
"prefer-template": ["off"],
|
||||
"quote-props": ["error", "as-needed"],
|
||||
"radix": ["error", "as-needed"],
|
||||
"require-atomic-updates": ["error"],
|
||||
"require-await": ["error"],
|
||||
"require-jsdoc": ["warn"],
|
||||
"require-yield": ["error"],
|
||||
"semi-style": ["error"],
|
||||
"sort-imports": ["off"],
|
||||
"sort-keys": ["off"],
|
||||
"sort-vars": ["off"],
|
||||
"strict": ["error"],
|
||||
"switch-colon-spacing": ["error"],
|
||||
"vars-on-top": ["warn"],
|
||||
"wrap-regex": ["error"],
|
||||
|
||||
"semi": ["error", "always"],
|
||||
"indent": ["error", 2, {"outerIIFEBody": 0}],
|
||||
"object-property-newline": 0,
|
||||
"one-var": 0,
|
||||
"no-var": 2,
|
||||
"prefer-const": 2,
|
||||
"no-extra-semi": 2,
|
||||
"quote-props": [2, "as-needed"],
|
||||
"object-property-newline": ["off"],
|
||||
"one-var": ["off"],
|
||||
"object-curly-spacing": ["error", "never"],
|
||||
|
||||
"promise/catch-or-return": "error",
|
||||
"promise/no-return-wrap": "error",
|
||||
"promise/param-names": "error",
|
||||
"promise/always-return": "error",
|
||||
"promise/no-native": "off",
|
||||
"promise/no-nesting": "warn",
|
||||
"promise/no-promise-in-callback": "warn",
|
||||
"promise/no-callback-in-promise": "warn",
|
||||
"promise/avoid-new": "warn",
|
||||
"promise/no-new-statics": "error",
|
||||
"promise/no-return-in-finally": "warn",
|
||||
"promise/valid-params": "warn",
|
||||
"promise/prefer-await-to-then": "error",
|
||||
"promise/prefer-await-to-callbacks": "warn",
|
||||
|
||||
"import/no-unresolved": "error",
|
||||
"import/named": "error",
|
||||
"import/default": "error",
|
||||
"import/namespace": "error",
|
||||
"import/no-restricted-paths": "off",
|
||||
"import/no-absolute-path": "error",
|
||||
"import/no-dynamic-require": "error",
|
||||
"import/no-internal-modules": "off",
|
||||
"import/no-webpack-loader-syntax": "error",
|
||||
"import/no-self-import": "error",
|
||||
"import/no-cycle": "off",
|
||||
"import/no-useless-path-segments": "error",
|
||||
"import/no-relative-parent-imports": "off",
|
||||
"import/export": "error",
|
||||
"import/no-named-as-default": "error",
|
||||
"import/no-named-as-default-member": "error",
|
||||
"import/no-deprecated": "error",
|
||||
"import/no-extraneous-dependencies": "error",
|
||||
"import/no-mutable-exports": "error",
|
||||
"import/unambiguous": "warn",
|
||||
"import/no-commonjs": "error",
|
||||
"import/no-amd": "error",
|
||||
"import/no-nodejs-modules": "off",
|
||||
"import/first": "error",
|
||||
"import/exports-last": "off",
|
||||
"import/no-duplicates": "error",
|
||||
"import/no-namespace": "off",
|
||||
"import/extensions": ["error", "always", {"ignorePackages": true}],
|
||||
"import/order": ["error", {"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
"internal",
|
||||
["parent", "sibling", "index"]
|
||||
]}],
|
||||
"import/newline-after-import": "error",
|
||||
"import/prefer-default-export": "off",
|
||||
"import/max-dependencies": "off",
|
||||
"import/no-unassigned-import": "off",
|
||||
"import/no-named-default": "error",
|
||||
"import/no-default-export": "off",
|
||||
"import/no-named-export": "off",
|
||||
"import/no-anonymous-default-export": "error",
|
||||
"import/group-exports": "off",
|
||||
"import/dynamic-import-chunkname": "off",
|
||||
|
||||
"jsdoc/check-param-names": 1,
|
||||
"jsdoc/check-tag-names": 1,
|
||||
"jsdoc/check-types": 1,
|
||||
|
@ -61,7 +333,7 @@
|
|||
|
||||
"jsdoc/no-undefined-types": ["off"],
|
||||
"jsdoc/valid-types": ["error"],
|
||||
"valid-jsdoc": ["off", {
|
||||
"valid-jsdoc": ["error", {
|
||||
"prefer": {
|
||||
"arg": "param",
|
||||
"argument": "param",
|
||||
|
@ -81,6 +353,16 @@
|
|||
"matchDescription": "^([A-Z][\\s\\S]*[.`?!])?$",
|
||||
"requireParamDescription": false,
|
||||
"requireReturnDescription": false
|
||||
}],
|
||||
"no-warning-comments": ["off"],
|
||||
"default-case": ["off"],
|
||||
"complexity": ["off"],
|
||||
"require-unicode-regexp": ["off"],
|
||||
"capitalized-comments": ["off"],
|
||||
"no-magic-numbers": ["off"],
|
||||
"max-len": ["off", {
|
||||
"ignoreUrls": true,
|
||||
"ignoreRegExpLiterals": true
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import {NS} from './namespaces.js';
|
|||
const $ = jQuery;
|
||||
|
||||
const supportsSVG_ = (function () {
|
||||
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
|
||||
return Boolean(document.createElementNS && document.createElementNS(NS.SVG, 'svg').createSVGRect);
|
||||
}());
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,7 @@ const {userAgent} = navigator;
|
|||
const svg = document.createElementNS(NS.SVG, 'svg');
|
||||
|
||||
// Note: Browser sniffing should only be used if no other detection method is possible
|
||||
const isOpera_ = !!window.opera;
|
||||
const isOpera_ = Boolean(window.opera);
|
||||
const isWebkit_ = userAgent.includes('AppleWebKit');
|
||||
const isGecko_ = userAgent.includes('Gecko/');
|
||||
const isIE_ = userAgent.includes('MSIE');
|
||||
|
@ -39,11 +39,11 @@ const isMac_ = userAgent.includes('Macintosh');
|
|||
const isTouch_ = 'ontouchstart' in window;
|
||||
|
||||
const supportsSelectors_ = (function () {
|
||||
return !!svg.querySelector;
|
||||
return Boolean(svg.querySelector);
|
||||
}());
|
||||
|
||||
const supportsXpath_ = (function () {
|
||||
return !!document.evaluate;
|
||||
return Boolean(document.evaluate);
|
||||
}());
|
||||
|
||||
// segList functions (for FF1.5 and 2.0)
|
||||
|
|
|
@ -11,6 +11,15 @@
|
|||
import RGBColor from './rgbcolor.js';
|
||||
import {canvasRGBA} from '../external/stackblur-canvas/dist/stackblur-es.js';
|
||||
|
||||
/**
|
||||
* Whether a value is `null` or `undefined`.
|
||||
* @param {Any} val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isNullish = (val) => {
|
||||
return val === null || val === undefined;
|
||||
};
|
||||
|
||||
let canvasRGBA_ = canvasRGBA;
|
||||
|
||||
/**
|
||||
|
@ -63,7 +72,7 @@ export const setStackBlurCanvasRGBA = (cb) => {
|
|||
*/
|
||||
export const canvg = function (target, s, opts) {
|
||||
// no parameters
|
||||
if (target == null && s == null && opts == null) {
|
||||
if (isNullish(target) && isNullish(s) && isNullish(opts)) {
|
||||
const svgTags = document.querySelectorAll('svg');
|
||||
return Promise.all([...svgTags].map((svgTag) => {
|
||||
const c = document.createElement('canvas');
|
||||
|
@ -82,7 +91,7 @@ export const canvg = function (target, s, opts) {
|
|||
}
|
||||
|
||||
// store class on canvas
|
||||
if (target.svg != null) target.svg.stop();
|
||||
if (!isNullish(target.svg)) target.svg.stop();
|
||||
const svg = build(opts || {});
|
||||
// on i.e. 8 for flash canvas, we can't assign the property so check for it
|
||||
if (!(target.childNodes.length === 1 && target.childNodes[0].nodeName === 'OBJECT')) {
|
||||
|
@ -113,9 +122,9 @@ function build (opts) {
|
|||
svg.FRAMERATE = 30;
|
||||
svg.MAX_VIRTUAL_PIXELS = 30000;
|
||||
|
||||
svg.log = function (msg) {};
|
||||
svg.log = function (msg) { /* */ };
|
||||
if (svg.opts.log === true && typeof console !== 'undefined') {
|
||||
svg.log = function (msg) { console.log(msg); };
|
||||
svg.log = function (msg) { console.log(msg); }; // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
// globals
|
||||
|
@ -139,7 +148,7 @@ function build (opts) {
|
|||
width () { return this.Current().width; },
|
||||
height () { return this.Current().height; },
|
||||
ComputeSize (d) {
|
||||
if (d != null && typeof d === 'number') return d;
|
||||
if (!isNullish(d) && typeof d === 'number') return d;
|
||||
if (d === 'x') return this.width();
|
||||
if (d === 'y') return this.height();
|
||||
return Math.sqrt(
|
||||
|
@ -190,13 +199,12 @@ function build (opts) {
|
|||
if (window.DOMParser) {
|
||||
const parser = new DOMParser();
|
||||
return parser.parseFromString(xml, 'text/xml');
|
||||
} else {
|
||||
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
|
||||
const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDoc.async = 'false';
|
||||
xmlDoc.loadXML(xml);
|
||||
return xmlDoc;
|
||||
}
|
||||
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
|
||||
const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDoc.async = 'false';
|
||||
xmlDoc.loadXML(xml);
|
||||
return xmlDoc;
|
||||
};
|
||||
|
||||
// text extensions
|
||||
|
@ -226,7 +234,7 @@ function build (opts) {
|
|||
}
|
||||
|
||||
hasValue () {
|
||||
return (this.value != null && this.value !== '');
|
||||
return (!isNullish(this.value) && this.value !== '');
|
||||
}
|
||||
|
||||
// return the numerical value of the property
|
||||
|
@ -234,8 +242,8 @@ function build (opts) {
|
|||
if (!this.hasValue()) return 0;
|
||||
|
||||
let n = parseFloat(this.value);
|
||||
if ((this.value + '').match(/%$/)) {
|
||||
n = n / 100.0;
|
||||
if (String(this.value).match(/%$/)) {
|
||||
n /= 100.0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -254,7 +262,7 @@ function build (opts) {
|
|||
// augment the current color value with the opacity
|
||||
addOpacity (opacityProp) {
|
||||
let newValue = this.value;
|
||||
if (opacityProp.value != null && opacityProp.value !== '' && typeof this.value === 'string') { // can only add opacity to colors, not patterns
|
||||
if (!isNullish(opacityProp.value) && opacityProp.value !== '' && typeof this.value === 'string') { // can only add opacity to colors, not patterns
|
||||
const color = new RGBColor(this.value);
|
||||
if (color.ok) {
|
||||
newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')';
|
||||
|
@ -280,12 +288,12 @@ function build (opts) {
|
|||
let def = this.getDefinition();
|
||||
|
||||
// gradient
|
||||
if (def != null && def.createGradient) {
|
||||
if (!isNullish(def) && def.createGradient) {
|
||||
return def.createGradient(svg.ctx, e, opacityProp);
|
||||
}
|
||||
|
||||
// pattern
|
||||
if (def != null && def.createPattern) {
|
||||
if (!isNullish(def) && def.createPattern) {
|
||||
if (def.getHrefAttribute().hasValue()) {
|
||||
const pt = def.attribute('patternTransform');
|
||||
def = def.getHrefAttribute().getDefinition();
|
||||
|
@ -312,14 +320,13 @@ function build (opts) {
|
|||
}
|
||||
|
||||
getUnits () {
|
||||
const s = this.value + '';
|
||||
return s.replace(/[0-9.-]/g, '');
|
||||
return String(this.value).replace(/[0-9.-]/g, '');
|
||||
}
|
||||
|
||||
// get the length as pixels
|
||||
toPixels (viewPort, processPercent) {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
|
||||
if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
|
||||
if (s.match(/px$/)) return this.numValue();
|
||||
|
@ -338,7 +345,7 @@ function build (opts) {
|
|||
// get the time as milliseconds
|
||||
toMilliseconds () {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/s$/)) return this.numValue() * 1000;
|
||||
if (s.match(/ms$/)) return this.numValue();
|
||||
return this.numValue();
|
||||
|
@ -348,7 +355,7 @@ function build (opts) {
|
|||
// get the angle as radians
|
||||
toRadians () {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
|
||||
if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
|
||||
if (s.match(/rad$/)) return this.numValue();
|
||||
|
@ -368,7 +375,7 @@ function build (opts) {
|
|||
Weights: 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit',
|
||||
|
||||
CreateFont (fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
|
||||
const f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
|
||||
const f = !isNullish(inherit) ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
|
||||
return {
|
||||
fontFamily: fontFamily || f.fontFamily,
|
||||
fontSize: fontSize || f.fontSize,
|
||||
|
@ -474,7 +481,7 @@ function build (opts) {
|
|||
height () { return this.y2 - this.y1; }
|
||||
|
||||
addPoint (x, y) {
|
||||
if (x != null) {
|
||||
if (!isNullish(x)) {
|
||||
if (isNaN(this.x1) || isNaN(this.x2)) {
|
||||
this.x1 = x;
|
||||
this.x2 = x;
|
||||
|
@ -483,7 +490,7 @@ function build (opts) {
|
|||
if (x > this.x2) this.x2 = x;
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
if (!isNullish(y)) {
|
||||
if (isNaN(this.y1) || isNaN(this.y2)) {
|
||||
this.y1 = y;
|
||||
this.y2 = y;
|
||||
|
@ -710,7 +717,7 @@ function build (opts) {
|
|||
else if (meetOrSlice === 'slice') ctx.scale(scaleMax, scaleMax);
|
||||
|
||||
// translate
|
||||
ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
|
||||
ctx.translate(isNullish(minX) ? 0 : -minX, isNullish(minY) ? 0 : -minY);
|
||||
};
|
||||
|
||||
// elements
|
||||
|
@ -724,7 +731,7 @@ function build (opts) {
|
|||
this.attributes = {};
|
||||
this.styles = {};
|
||||
this.children = [];
|
||||
if (node != null && node.nodeType === 1) { // ELEMENT_NODE
|
||||
if (!isNullish(node) && node.nodeType === 1) { // ELEMENT_NODE
|
||||
// add children
|
||||
[...node.childNodes].forEach((childNode) => {
|
||||
if (childNode.nodeType === 1) {
|
||||
|
@ -749,7 +756,7 @@ function build (opts) {
|
|||
});
|
||||
// add tag styles
|
||||
let styles = svg.Styles[node.nodeName];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
|
@ -760,13 +767,13 @@ function build (opts) {
|
|||
const classes = svg.compressSpaces(this.attribute('class').value).split(' ');
|
||||
classes.forEach((clss) => {
|
||||
styles = svg.Styles['.' + clss];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
}
|
||||
styles = svg.Styles[node.nodeName + '.' + clss];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
|
@ -777,7 +784,7 @@ function build (opts) {
|
|||
// add id styles
|
||||
if (this.attribute('id').hasValue()) {
|
||||
const styles = svg.Styles['#' + this.attribute('id').value];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
|
@ -799,7 +806,7 @@ function build (opts) {
|
|||
|
||||
// add id
|
||||
if (this.attribute('id').hasValue()) {
|
||||
if (svg.Definitions[this.attribute('id').value] == null) {
|
||||
if (isNullish(svg.Definitions[this.attribute('id').value])) {
|
||||
svg.Definitions[this.attribute('id').value] = this;
|
||||
}
|
||||
}
|
||||
|
@ -809,7 +816,7 @@ function build (opts) {
|
|||
// get or create attribute
|
||||
attribute (name, createIfNotExists) {
|
||||
let a = this.attributes[name];
|
||||
if (a != null) return a;
|
||||
if (!isNullish(a)) return a;
|
||||
|
||||
if (createIfNotExists === true) { a = new svg.Property(name, ''); this.attributes[name] = a; }
|
||||
return a || svg.EmptyProperty;
|
||||
|
@ -827,19 +834,19 @@ function build (opts) {
|
|||
// get or create style, crawls up node tree
|
||||
style (name, createIfNotExists, skipAncestors) {
|
||||
let s = this.styles[name];
|
||||
if (s != null) return s;
|
||||
if (!isNullish(s)) return s;
|
||||
|
||||
const a = this.attribute(name);
|
||||
if (a != null && a.hasValue()) {
|
||||
if (!isNullish(a) && a.hasValue()) {
|
||||
this.styles[name] = a; // move up to me to cache
|
||||
return a;
|
||||
}
|
||||
|
||||
if (skipAncestors !== true) {
|
||||
const p = this.parent;
|
||||
if (p != null) {
|
||||
if (!isNullish(p)) {
|
||||
const ps = p.style(name);
|
||||
if (ps != null && ps.hasValue()) {
|
||||
if (!isNullish(ps) && ps.hasValue()) {
|
||||
return ps;
|
||||
}
|
||||
}
|
||||
|
@ -860,10 +867,10 @@ function build (opts) {
|
|||
ctx.save();
|
||||
if (this.attribute('mask').hasValue()) { // mask
|
||||
const mask = this.attribute('mask').getDefinition();
|
||||
if (mask != null) mask.apply(ctx, this);
|
||||
if (!isNullish(mask)) mask.apply(ctx, this);
|
||||
} else if (this.style('filter').hasValue()) { // filter
|
||||
const filter = this.style('filter').getDefinition();
|
||||
if (filter != null) filter.apply(ctx, this);
|
||||
if (!isNullish(filter)) filter.apply(ctx, this);
|
||||
} else {
|
||||
this.setContext(ctx);
|
||||
this.renderChildren(ctx);
|
||||
|
@ -903,7 +910,7 @@ function build (opts) {
|
|||
// fill
|
||||
if (this.style('fill').isUrlDefinition()) {
|
||||
const fs = this.style('fill').getFillStyleDefinition(this, this.style('fill-opacity'));
|
||||
if (fs != null) ctx.fillStyle = fs;
|
||||
if (!isNullish(fs)) ctx.fillStyle = fs;
|
||||
} else if (this.style('fill').hasValue()) {
|
||||
const fillStyle = this.style('fill');
|
||||
if (fillStyle.value === 'currentColor') fillStyle.value = this.style('color').value;
|
||||
|
@ -918,7 +925,7 @@ function build (opts) {
|
|||
// stroke
|
||||
if (this.style('stroke').isUrlDefinition()) {
|
||||
const fs = this.style('stroke').getFillStyleDefinition(this, this.style('stroke-opacity'));
|
||||
if (fs != null) ctx.strokeStyle = fs;
|
||||
if (!isNullish(fs)) ctx.strokeStyle = fs;
|
||||
} else if (this.style('stroke').hasValue()) {
|
||||
const strokeStyle = this.style('stroke');
|
||||
if (strokeStyle.value === 'currentColor') strokeStyle.value = this.style('color').value;
|
||||
|
@ -963,7 +970,8 @@ function build (opts) {
|
|||
this.style('font-variant').value,
|
||||
this.style('font-weight').value,
|
||||
this.style('font-size').hasValue() ? this.style('font-size').toPixels() + 'px' : '',
|
||||
this.style('font-family').value).toString();
|
||||
this.style('font-family').value
|
||||
).toString();
|
||||
}
|
||||
|
||||
// transform
|
||||
|
@ -975,7 +983,7 @@ function build (opts) {
|
|||
// clip
|
||||
if (this.style('clip-path', false, true).hasValue()) {
|
||||
const clip = this.style('clip-path', false, true).getDefinition();
|
||||
if (clip != null) clip.apply(ctx);
|
||||
if (!isNullish(clip)) clip.apply(ctx);
|
||||
}
|
||||
|
||||
// opacity
|
||||
|
@ -987,7 +995,7 @@ function build (opts) {
|
|||
|
||||
svg.Element.PathElementBase = class extends svg.Element.RenderedElementBase {
|
||||
path (ctx) {
|
||||
if (ctx != null) ctx.beginPath();
|
||||
if (!isNullish(ctx)) ctx.beginPath();
|
||||
return new svg.BoundingBox();
|
||||
}
|
||||
|
||||
|
@ -1004,7 +1012,7 @@ function build (opts) {
|
|||
if (ctx.strokeStyle !== '') ctx.stroke();
|
||||
|
||||
const markers = this.getMarkers();
|
||||
if (markers != null) {
|
||||
if (!isNullish(markers)) {
|
||||
if (this.style('marker-start').isUrlDefinition()) {
|
||||
const marker = this.style('marker-start').getDefinition();
|
||||
marker.render(ctx, markers[0][0], markers[0][1]);
|
||||
|
@ -1123,7 +1131,7 @@ function build (opts) {
|
|||
if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
|
||||
rx = Math.min(rx, width / 2.0);
|
||||
ry = Math.min(ry, height / 2.0);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + rx, y);
|
||||
ctx.lineTo(x + width - rx, y);
|
||||
|
@ -1148,7 +1156,7 @@ function build (opts) {
|
|||
const cy = this.attribute('cy').toPixels('y');
|
||||
const r = this.attribute('r').toPixels();
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
|
||||
ctx.closePath();
|
||||
|
@ -1167,7 +1175,7 @@ function build (opts) {
|
|||
const cx = this.attribute('cx').toPixels('x');
|
||||
const cy = this.attribute('cy').toPixels('y');
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx, cy - ry);
|
||||
ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy);
|
||||
|
@ -1186,13 +1194,14 @@ function build (opts) {
|
|||
getPoints () {
|
||||
return [
|
||||
new svg.Point(this.attribute('x1').toPixels('x'), this.attribute('y1').toPixels('y')),
|
||||
new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))];
|
||||
new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))
|
||||
];
|
||||
}
|
||||
|
||||
path (ctx) {
|
||||
const points = this.getPoints();
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
ctx.lineTo(points[1].x, points[1].y);
|
||||
|
@ -1218,14 +1227,14 @@ function build (opts) {
|
|||
path (ctx) {
|
||||
const {x, y} = this.points[0];
|
||||
const bb = new svg.BoundingBox(x, y);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y);
|
||||
}
|
||||
for (let i = 1; i < this.points.length; i++) {
|
||||
const {x, y} = this.points[i];
|
||||
bb.addPoint(x, y);
|
||||
if (ctx != null) ctx.lineTo(x, y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(x, y);
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
@ -1244,7 +1253,7 @@ function build (opts) {
|
|||
svg.Element.polygon = class extends svg.Element.polyline {
|
||||
path (ctx) {
|
||||
const bb = super.path(ctx);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.lineTo(this.points[0].x, this.points[0].y);
|
||||
ctx.closePath();
|
||||
}
|
||||
|
@ -1289,7 +1298,7 @@ function build (opts) {
|
|||
|
||||
isCommandOrEnd () {
|
||||
if (this.isEnd()) return true;
|
||||
return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
|
||||
return !isNullish(this.tokens[this.i + 1].match(/^[A-Za-z]$/));
|
||||
},
|
||||
|
||||
isRelativeCommand () {
|
||||
|
@ -1363,10 +1372,10 @@ function build (opts) {
|
|||
|
||||
addMarker (p, from, priorTo) {
|
||||
// if the last angle isn't filled in because we didn't have this point yet ...
|
||||
if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
|
||||
if (!isNullish(priorTo) && this.angles.length > 0 && isNullish(this.angles[this.angles.length - 1])) {
|
||||
this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
|
||||
}
|
||||
this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
|
||||
this.addMarkerAngle(p, isNullish(from) ? null : from.angleTo(p));
|
||||
},
|
||||
|
||||
addMarkerAngle (p, a) {
|
||||
|
@ -1377,9 +1386,9 @@ function build (opts) {
|
|||
getMarkerPoints () { return this.points; },
|
||||
getMarkerAngles () {
|
||||
for (let i = 0; i < this.angles.length; i++) {
|
||||
if (this.angles[i] == null) {
|
||||
if (isNullish(this.angles[i])) {
|
||||
for (let j = i + 1; j < this.angles.length; j++) {
|
||||
if (this.angles[j] != null) {
|
||||
if (!isNullish(this.angles[j])) {
|
||||
this.angles[i] = this.angles[j];
|
||||
break;
|
||||
}
|
||||
|
@ -1396,7 +1405,7 @@ function build (opts) {
|
|||
pp.reset();
|
||||
|
||||
const bb = new svg.BoundingBox();
|
||||
if (ctx != null) ctx.beginPath();
|
||||
if (!isNullish(ctx)) ctx.beginPath();
|
||||
while (!pp.isEnd()) {
|
||||
pp.nextCommand();
|
||||
switch (pp.command) {
|
||||
|
@ -1405,13 +1414,13 @@ function build (opts) {
|
|||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.moveTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.moveTo(p.x, p.y);
|
||||
pp.start = pp.current;
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p, pp.start);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
|
@ -1421,7 +1430,7 @@ function build (opts) {
|
|||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p, c);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
|
@ -1431,7 +1440,7 @@ function build (opts) {
|
|||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
|
@ -1441,7 +1450,7 @@ function build (opts) {
|
|||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
|
@ -1453,7 +1462,7 @@ function build (opts) {
|
|||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, p1);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
|
@ -1465,7 +1474,7 @@ function build (opts) {
|
|||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, p1);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
|
@ -1476,7 +1485,7 @@ function build (opts) {
|
|||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
|
@ -1488,7 +1497,7 @@ function build (opts) {
|
|||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
|
@ -1560,7 +1569,7 @@ function build (opts) {
|
|||
pp.addMarkerAngle(cp, ah - dir * Math.PI);
|
||||
|
||||
bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
const r = rx > ry ? rx : ry;
|
||||
const sx = rx > ry ? 1 : rx / ry;
|
||||
const sy = rx > ry ? ry / rx : 1;
|
||||
|
@ -1577,7 +1586,7 @@ function build (opts) {
|
|||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
if (ctx != null) ctx.closePath();
|
||||
if (!isNullish(ctx)) ctx.closePath();
|
||||
pp.current = pp.start;
|
||||
}
|
||||
}
|
||||
|
@ -1604,10 +1613,10 @@ function build (opts) {
|
|||
|
||||
// render me using a temporary svg element
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', width + 'px');
|
||||
tempSvg.attributes['height'] = new svg.Property('height', height + 'px');
|
||||
tempSvg.attributes['transform'] = new svg.Property('transform', this.attribute('patternTransform').value);
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes.width = new svg.Property('width', width + 'px');
|
||||
tempSvg.attributes.height = new svg.Property('height', height + 'px');
|
||||
tempSvg.attributes.transform = new svg.Property('transform', this.attribute('patternTransform').value);
|
||||
tempSvg.children = this.children;
|
||||
|
||||
const c = document.createElement('canvas');
|
||||
|
@ -1641,13 +1650,13 @@ function build (opts) {
|
|||
|
||||
// render me using a temporary svg element
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
|
||||
tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
|
||||
tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
|
||||
tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
|
||||
tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes.refX = new svg.Property('refX', this.attribute('refX').value);
|
||||
tempSvg.attributes.refY = new svg.Property('refY', this.attribute('refY').value);
|
||||
tempSvg.attributes.width = new svg.Property('width', this.attribute('markerWidth').value);
|
||||
tempSvg.attributes.height = new svg.Property('height', this.attribute('markerHeight').value);
|
||||
tempSvg.attributes.fill = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
|
||||
tempSvg.attributes.stroke = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
|
||||
tempSvg.children = this.children;
|
||||
tempSvg.render(ctx);
|
||||
|
||||
|
@ -1698,7 +1707,7 @@ function build (opts) {
|
|||
};
|
||||
|
||||
const g = this.getGradient(ctx, element);
|
||||
if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
|
||||
if (isNullish(g)) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
|
||||
stopsContainer.stops.forEach(({offset, color}) => {
|
||||
g.addColorStop(offset, addParentOpacity(color));
|
||||
});
|
||||
|
@ -1708,20 +1717,20 @@ function build (opts) {
|
|||
const rootView = svg.ViewPort.viewPorts[0];
|
||||
|
||||
const rect = new svg.Element.rect();
|
||||
rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes.x = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes.y = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes.width = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes.height = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
|
||||
|
||||
const group = new svg.Element.g();
|
||||
group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);
|
||||
group.attributes.transform = new svg.Property('transform', this.attribute('gradientTransform').value);
|
||||
group.children = [rect];
|
||||
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['x'] = new svg.Property('x', 0);
|
||||
tempSvg.attributes['y'] = new svg.Property('y', 0);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', rootView.width);
|
||||
tempSvg.attributes['height'] = new svg.Property('height', rootView.height);
|
||||
tempSvg.attributes.x = new svg.Property('x', 0);
|
||||
tempSvg.attributes.y = new svg.Property('y', 0);
|
||||
tempSvg.attributes.width = new svg.Property('width', rootView.width);
|
||||
tempSvg.attributes.height = new svg.Property('height', rootView.height);
|
||||
tempSvg.children = [group];
|
||||
|
||||
const c = document.createElement('canvas');
|
||||
|
@ -1867,7 +1876,7 @@ function build (opts) {
|
|||
|
||||
update (delta) {
|
||||
// set initial value
|
||||
if (this.initialValue == null) {
|
||||
if (isNullish(this.initialValue)) {
|
||||
this.initialValue = this.getProperty().value;
|
||||
this.initialUnits = this.getProperty().getUnits();
|
||||
}
|
||||
|
@ -1949,7 +1958,7 @@ function build (opts) {
|
|||
const r = from.r + (to.r - from.r) * p.progress;
|
||||
const g = from.g + (to.g - from.g) * p.progress;
|
||||
const b = from.b + (to.b - from.b) * p.progress;
|
||||
return 'rgb(' + parseInt(r, 10) + ',' + parseInt(g, 10) + ',' + parseInt(b, 10) + ')';
|
||||
return 'rgb(' + parseInt(r) + ',' + parseInt(g) + ',' + parseInt(b) + ')';
|
||||
}
|
||||
return this.attribute('from').value;
|
||||
}
|
||||
|
@ -2048,8 +2057,8 @@ function build (opts) {
|
|||
super.setContext(ctx);
|
||||
|
||||
let textBaseline = this.style('dominant-baseline').toTextBaseline();
|
||||
if (textBaseline == null) textBaseline = this.style('alignment-baseline').toTextBaseline();
|
||||
if (textBaseline != null) ctx.textBaseline = textBaseline;
|
||||
if (isNullish(textBaseline)) textBaseline = this.style('alignment-baseline').toTextBaseline();
|
||||
if (!isNullish(textBaseline)) ctx.textBaseline = textBaseline;
|
||||
}
|
||||
|
||||
getBoundingBox () {
|
||||
|
@ -2124,18 +2133,18 @@ function build (opts) {
|
|||
if (i > 0 && text[i - 1] !== ' ' && (i === text.length - 1 || text[i + 1] === ' ')) arabicForm = 'initial';
|
||||
if (typeof font.glyphs[c] !== 'undefined') {
|
||||
glyph = font.glyphs[c][arabicForm];
|
||||
if (glyph == null && font.glyphs[c].type === 'glyph') glyph = font.glyphs[c];
|
||||
if (isNullish(glyph) && font.glyphs[c].type === 'glyph') glyph = font.glyphs[c];
|
||||
}
|
||||
} else {
|
||||
glyph = font.glyphs[c];
|
||||
}
|
||||
if (glyph == null) glyph = font.missingGlyph;
|
||||
if (isNullish(glyph)) glyph = font.missingGlyph;
|
||||
return glyph;
|
||||
}
|
||||
|
||||
renderChildren (ctx) {
|
||||
const customFont = this.parent.style('font-family').getDefinition();
|
||||
if (customFont != null) {
|
||||
if (!isNullish(customFont)) {
|
||||
const fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
|
||||
const fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
|
||||
let text = this.getText();
|
||||
|
@ -2182,7 +2191,7 @@ function build (opts) {
|
|||
|
||||
measureText (ctx) {
|
||||
const customFont = this.parent.style('font-family').getDefinition();
|
||||
if (customFont != null) {
|
||||
if (!isNullish(customFont)) {
|
||||
const fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
|
||||
let measure = 0;
|
||||
let text = this.getText();
|
||||
|
@ -2225,7 +2234,8 @@ function build (opts) {
|
|||
svg.Element.tref = class extends svg.Element.TextElementBase {
|
||||
getText () {
|
||||
const element = this.getHrefAttribute().getDefinition();
|
||||
if (element != null) return element.children[0].getText();
|
||||
if (!isNullish(element)) return element.children[0].getText();
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2290,13 +2300,12 @@ function build (opts) {
|
|||
if (svg.opts.useCORS === true) {
|
||||
this.img.crossOrigin = 'Anonymous';
|
||||
}
|
||||
const self = this;
|
||||
this.img.onload = function () {
|
||||
self.loaded = true;
|
||||
this.img.onload = () => {
|
||||
this.loaded = true;
|
||||
};
|
||||
this.img.onerror = function () {
|
||||
this.img.onerror = () => {
|
||||
svg.log('ERROR: image "' + href + '" not found');
|
||||
self.loaded = true;
|
||||
this.loaded = true;
|
||||
};
|
||||
this.img.src = href;
|
||||
} else {
|
||||
|
@ -2387,14 +2396,14 @@ function build (opts) {
|
|||
const prop = cssProp.indexOf(':');
|
||||
const name = cssProp.substr(0, prop);
|
||||
const value = cssProp.substr(prop + 1, cssProp.length - prop);
|
||||
if (name != null && value != null) {
|
||||
if (!isNullish(name) && !isNullish(value)) {
|
||||
props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
|
||||
}
|
||||
});
|
||||
svg.Styles[cssClass] = props;
|
||||
if (cssClass === '@font-face') {
|
||||
const fontFamily = props['font-family'].value.replace(/"/g, '');
|
||||
const srcs = props['src'].value.split(',');
|
||||
const srcs = props.src.value.split(',');
|
||||
srcs.forEach((src) => {
|
||||
if (src.includes('format("svg")')) {
|
||||
const urlStart = src.indexOf('url');
|
||||
|
@ -2433,31 +2442,31 @@ function build (opts) {
|
|||
|
||||
path (ctx) {
|
||||
const {_el: element} = this;
|
||||
if (element != null) element.path(ctx);
|
||||
if (!isNullish(element)) element.path(ctx);
|
||||
}
|
||||
|
||||
getBoundingBox () {
|
||||
const {_el: element} = this;
|
||||
if (element != null) return element.getBoundingBox();
|
||||
if (!isNullish(element)) return element.getBoundingBox();
|
||||
}
|
||||
|
||||
renderChildren (ctx) {
|
||||
const {_el: element} = this;
|
||||
if (element != null) {
|
||||
if (!isNullish(element)) {
|
||||
let tempSvg = element;
|
||||
if (element.type === 'symbol') {
|
||||
// render me using a temporary svg element in symbol cases (https://www.w3.org/TR/SVG/struct.html#UseElement)
|
||||
tempSvg = new svg.Element.svg();
|
||||
tempSvg.type = 'svg';
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', element.attribute('viewBox').value);
|
||||
tempSvg.attributes['preserveAspectRatio'] = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
|
||||
tempSvg.attributes['overflow'] = new svg.Property('overflow', element.attribute('overflow').value);
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', element.attribute('viewBox').value);
|
||||
tempSvg.attributes.preserveAspectRatio = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
|
||||
tempSvg.attributes.overflow = new svg.Property('overflow', element.attribute('overflow').value);
|
||||
tempSvg.children = element.children;
|
||||
}
|
||||
if (tempSvg.type === 'svg') {
|
||||
// if symbol or svg, inherit width/height from me
|
||||
if (this.attribute('width').hasValue()) tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
|
||||
if (this.attribute('height').hasValue()) tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
|
||||
if (this.attribute('width').hasValue()) tempSvg.attributes.width = new svg.Property('width', this.attribute('width').value);
|
||||
if (this.attribute('height').hasValue()) tempSvg.attributes.height = new svg.Property('height', this.attribute('height').value);
|
||||
}
|
||||
const oldParent = tempSvg.parent;
|
||||
tempSvg.parent = null;
|
||||
|
@ -2762,14 +2771,14 @@ function build (opts) {
|
|||
// bind mouse
|
||||
if (svg.opts.ignoreMouse !== true) {
|
||||
ctx.canvas.onclick = function (e) {
|
||||
const args = e != null
|
||||
const args = !isNullish(e)
|
||||
? [e.clientX, e.clientY]
|
||||
: [event.clientX, event.clientY];
|
||||
const {x, y} = mapXY(new svg.Point(...args));
|
||||
svg.Mouse.onclick(x, y);
|
||||
};
|
||||
ctx.canvas.onmousemove = function (e) {
|
||||
const args = e != null
|
||||
const args = !isNullish(e)
|
||||
? [e.clientX, e.clientY]
|
||||
: [event.clientX, event.clientY];
|
||||
const {x, y} = mapXY(new svg.Point(...args));
|
||||
|
@ -2812,17 +2821,17 @@ function build (opts) {
|
|||
}
|
||||
svg.ViewPort.SetCurrent(cWidth, cHeight);
|
||||
|
||||
if (svg.opts.offsetX != null) {
|
||||
if (!isNullish(svg.opts.offsetX)) {
|
||||
e.attribute('x', true).value = svg.opts.offsetX;
|
||||
}
|
||||
if (svg.opts.offsetY != null) {
|
||||
if (!isNullish(svg.opts.offsetY)) {
|
||||
e.attribute('y', true).value = svg.opts.offsetY;
|
||||
}
|
||||
if (svg.opts.scaleWidth != null || svg.opts.scaleHeight != null) {
|
||||
if (!isNullish(svg.opts.scaleWidth) || !isNullish(svg.opts.scaleHeight)) {
|
||||
const viewBox = svg.ToNumberArray(e.attribute('viewBox').value);
|
||||
let xRatio = null, yRatio = null;
|
||||
|
||||
if (svg.opts.scaleWidth != null) {
|
||||
if (!isNullish(svg.opts.scaleWidth)) {
|
||||
if (e.attribute('width').hasValue()) {
|
||||
xRatio = e.attribute('width').toPixels('x') / svg.opts.scaleWidth;
|
||||
} else if (!isNaN(viewBox[2])) {
|
||||
|
@ -2830,7 +2839,7 @@ function build (opts) {
|
|||
}
|
||||
}
|
||||
|
||||
if (svg.opts.scaleHeight != null) {
|
||||
if (!isNullish(svg.opts.scaleHeight)) {
|
||||
if (e.attribute('height').hasValue()) {
|
||||
yRatio = e.attribute('height').toPixels('y') / svg.opts.scaleHeight;
|
||||
} else if (!isNaN(viewBox[3])) {
|
||||
|
@ -2838,8 +2847,8 @@ function build (opts) {
|
|||
}
|
||||
}
|
||||
|
||||
if (xRatio == null) { xRatio = yRatio; }
|
||||
if (yRatio == null) { yRatio = xRatio; }
|
||||
if (isNullish(xRatio)) { xRatio = yRatio; }
|
||||
if (isNullish(yRatio)) { yRatio = xRatio; }
|
||||
|
||||
e.attribute('width', true).value = svg.opts.scaleWidth;
|
||||
e.attribute('height', true).value = svg.opts.scaleHeight;
|
||||
|
|
|
@ -158,9 +158,9 @@ const colorDefs = [
|
|||
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process (bits) {
|
||||
return [
|
||||
parseInt(bits[1], 10),
|
||||
parseInt(bits[2], 10),
|
||||
parseInt(bits[3], 10)
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
|
@ -279,8 +279,7 @@ export default class RGBColor {
|
|||
margin: 3px;
|
||||
border: 1px solid black;
|
||||
background: ${listColor.toHex()};
|
||||
color: ${listColor.toHex()};`
|
||||
;
|
||||
color: ${listColor.toHex()};`;
|
||||
exampleDiv.append('test');
|
||||
const listItemValue = ` ${examples[i]} -> ${listColor.toRGB()} -> ${listColor.toHex()}`;
|
||||
listItem.append(exampleDiv, listItemValue);
|
||||
|
|
|
@ -93,9 +93,9 @@ const injectExtendedContextMenuItemIntoDom = function (menuItem) {
|
|||
* @returns {undefined}
|
||||
*/
|
||||
export const injectExtendedContextMenuItemsIntoDom = function () {
|
||||
for (const menuItem in contextMenuExtensions) {
|
||||
injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]);
|
||||
}
|
||||
Object.values(contextMenuExtensions).forEach((menuItem) => {
|
||||
injectExtendedContextMenuItemIntoDom(menuItem);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @function module:contextmenu.resetCustomMenus
|
||||
|
|
|
@ -74,8 +74,7 @@ function jQueryContextMenu ($) {
|
|||
// Add contextMenu class
|
||||
menu.addClass('contextMenu');
|
||||
// Simulate a true right click
|
||||
$(this).bind('mousedown', function (e) {
|
||||
const evt = e;
|
||||
$(this).bind('mousedown', function (evt) {
|
||||
$(this).mouseup(function (e) {
|
||||
const srcElement = $(this);
|
||||
srcElement.unbind('mouseup');
|
||||
|
@ -109,8 +108,8 @@ function jQueryContextMenu ($) {
|
|||
});
|
||||
|
||||
// Keyboard
|
||||
doc.keypress(function (e) {
|
||||
switch (e.keyCode) {
|
||||
doc.keypress(function (ev) {
|
||||
switch (ev.keyCode) {
|
||||
case 38: // up
|
||||
if (!menu.find('LI.hover').length) {
|
||||
menu.find('LI:last').addClass('hover');
|
||||
|
@ -143,7 +142,9 @@ function jQueryContextMenu ($) {
|
|||
$('.contextMenu').hide();
|
||||
// Callback
|
||||
if (callback) {
|
||||
callback($(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y});
|
||||
callback($(this).attr('href').substr(1), $(srcElement), {
|
||||
x: x - offset.left, y: y - offset.top, docX: x, docY: y
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -17,8 +17,10 @@ import {getTransformList} from './svgtransformlist.js';
|
|||
const $ = jQuery;
|
||||
|
||||
// this is how we map paths to our preferred relative segment types
|
||||
const pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
||||
const pathMap = [
|
||||
0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'
|
||||
];
|
||||
|
||||
/**
|
||||
* @interface module:coords.EditorContext
|
||||
|
@ -59,9 +61,9 @@ export const remapElement = function (selected, changes, m) {
|
|||
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
|
||||
finishUp = function () {
|
||||
if (doSnapping) {
|
||||
for (const o in changes) {
|
||||
changes[o] = snapToGrid(changes[o]);
|
||||
}
|
||||
Object.entries(changes).forEach(([o, value]) => {
|
||||
changes[o] = snapToGrid(value);
|
||||
});
|
||||
}
|
||||
assignAttributes(selected, changes, 1000, true);
|
||||
},
|
||||
|
@ -297,8 +299,8 @@ export const remapElement = function (selected, changes, m) {
|
|||
break;
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
|
||||
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + Number(seg.largeArcFlag) +
|
||||
' ' + Number(seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 16: // absolute smooth cubic (S)
|
||||
|
|
|
@ -139,7 +139,7 @@ export class Drawing {
|
|||
const n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');
|
||||
// If already set in the DOM, use the nonce throughout the document
|
||||
// else, if randomizeIds(true) has been called, create and set the nonce.
|
||||
if (!!n && randIds !== RandomizeModes.NEVER_RANDOMIZE) {
|
||||
if (n && randIds !== RandomizeModes.NEVER_RANDOMIZE) {
|
||||
this.nonce_ = n;
|
||||
} else if (randIds === RandomizeModes.ALWAYS_RANDOMIZE) {
|
||||
this.setNonce(Math.floor(Math.random() * 100001));
|
||||
|
@ -253,7 +253,7 @@ export class Drawing {
|
|||
return false;
|
||||
}
|
||||
// extract the obj_num of this id
|
||||
const num = parseInt(id.substr(front.length), 10);
|
||||
const num = parseInt(id.substr(front.length));
|
||||
|
||||
// if we didn't get a positive number or we already released this number
|
||||
// then return false.
|
||||
|
@ -669,8 +669,8 @@ export class Drawing {
|
|||
* @returns {Element}
|
||||
*/
|
||||
copyElem (el) {
|
||||
const self = this;
|
||||
const getNextIdClosure = function () { return self.getNextId(); };
|
||||
const that = this;
|
||||
const getNextIdClosure = function () { return that.getNextId(); };
|
||||
return utilCopyElem(el, getNextIdClosure);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ let cbid = 0;
|
|||
*/
|
||||
function getCallbackSetter (funcName) {
|
||||
return function (...args) {
|
||||
const t = this, // New callback
|
||||
cbid = t.send(funcName, args, function () {}); // The callback (currently it's nothing, but will be set later)
|
||||
const that = this, // New callback
|
||||
callbackID = this.send(funcName, args, function () { /* */ }); // The callback (currently it's nothing, but will be set later)
|
||||
|
||||
return function (newCallback) {
|
||||
t.callbacks[cbid] = newCallback; // Set callback
|
||||
that.callbacks[callbackID] = newCallback; // Set callback
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -39,14 +39,14 @@ function getCallbackSetter (funcName) {
|
|||
* @param {JSON} data
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function addCallback (t, {result, error, id: cbid}) {
|
||||
if (typeof cbid === 'number' && t.callbacks[cbid]) {
|
||||
function addCallback (t, {result, error, id: callbackID}) {
|
||||
if (typeof callbackID === 'number' && t.callbacks[callbackID]) {
|
||||
// These should be safe both because we check `cbid` is numeric and
|
||||
// because the calls are from trusted origins
|
||||
if (result) {
|
||||
t.callbacks[cbid](result); // lgtm [js/remote-property-injection]
|
||||
t.callbacks[callbackID](result); // lgtm [js/remote-property-injection]
|
||||
} else {
|
||||
t.callbacks[cbid](error, 'error'); // lgtm [js/remote-property-injection]
|
||||
t.callbacks[callbackID](error, 'error'); // lgtm [js/remote-property-injection]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ function messageListener (e) {
|
|||
e.source !== this.frame.contentWindow ||
|
||||
(!allowedOrigins.includes('*') && !allowedOrigins.includes(e.origin))
|
||||
) {
|
||||
console.log(`The origin ${e.origin} was not whitelisted as an origin from which responses may be received by this ${window.origin} script.`);
|
||||
console.log(`The origin ${e.origin} was not whitelisted as an origin from which responses may be received by this ${window.origin} script.`); // eslint-disable-line no-console
|
||||
return;
|
||||
}
|
||||
addCallback(this, data);
|
||||
|
@ -136,7 +136,7 @@ class EmbeddedSVGEdit {
|
|||
* If supplied, it should probably be the same as svgEditor's allowedOrigins
|
||||
*/
|
||||
constructor (frame, allowedOrigins) {
|
||||
const t = this;
|
||||
const that = this;
|
||||
this.allowedOrigins = allowedOrigins || [];
|
||||
// Initialize communication
|
||||
this.frame = frame;
|
||||
|
@ -326,7 +326,7 @@ class EmbeddedSVGEdit {
|
|||
const keyboardEvent = new KeyboardEvent(e.type, {
|
||||
key, keyCode, charCode, which
|
||||
});
|
||||
t.frame.contentDocument.dispatchEvent(keyboardEvent);
|
||||
that.frame.contentDocument.dispatchEvent(keyboardEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -338,11 +338,11 @@ class EmbeddedSVGEdit {
|
|||
* @returns {Integer}
|
||||
*/
|
||||
send (name, args, callback) {
|
||||
const t = this;
|
||||
const that = this;
|
||||
cbid++;
|
||||
|
||||
this.callbacks[cbid] = callback;
|
||||
setTimeout((function (cbid) {
|
||||
setTimeout((function (callbackID) {
|
||||
return function () { // Delay for the callback to be set in case its synchronous
|
||||
/*
|
||||
* Todo: Handle non-JSON arguments and return values (undefined,
|
||||
|
@ -354,8 +354,8 @@ class EmbeddedSVGEdit {
|
|||
// We accept and post strings for the sake of IE9 support
|
||||
let sameOriginWithGlobal = false;
|
||||
try {
|
||||
sameOriginWithGlobal = window.location.origin === t.frame.contentWindow.location.origin &&
|
||||
t.frame.contentWindow.svgEditor.canvas;
|
||||
sameOriginWithGlobal = window.location.origin === that.frame.contentWindow.location.origin &&
|
||||
that.frame.contentWindow.svgEditor.canvas;
|
||||
} catch (err) {}
|
||||
|
||||
if (sameOriginWithGlobal) {
|
||||
|
@ -365,17 +365,17 @@ class EmbeddedSVGEdit {
|
|||
// of the current JSON-based communication API (e.g., not passing
|
||||
// callbacks). We might be able to address these shortcomings; see
|
||||
// the todo elsewhere in this file.
|
||||
const message = {id: cbid},
|
||||
{svgEditor: {canvas: svgCanvas}} = t.frame.contentWindow;
|
||||
const message = {id: callbackID},
|
||||
{svgEditor: {canvas: svgCanvas}} = that.frame.contentWindow;
|
||||
try {
|
||||
message.result = svgCanvas[name].apply(svgCanvas, args);
|
||||
message.result = svgCanvas[name](...args);
|
||||
} catch (err) {
|
||||
message.error = err.message;
|
||||
}
|
||||
addCallback(t, message);
|
||||
addCallback(that, message);
|
||||
} else { // Requires the ext-xdomain-messaging.js extension
|
||||
t.frame.contentWindow.postMessage(JSON.stringify({
|
||||
namespace: 'svgCanvas', id: cbid, name, args
|
||||
that.frame.contentWindow.postMessage(JSON.stringify({
|
||||
namespace: 'svgCanvas', id: callbackID, name, args
|
||||
}), '*');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -67,7 +67,7 @@ export default {
|
|||
}
|
||||
|
||||
function getOffset (side, line) {
|
||||
const giveOffset = !!line.getAttribute('marker-' + side);
|
||||
const giveOffset = line.getAttribute('marker-' + side);
|
||||
// const giveOffset = $(line).data(side+'_off');
|
||||
|
||||
// TODO: Make this number (5) be based on marker width/height
|
||||
|
@ -170,7 +170,7 @@ export default {
|
|||
['start', 'end'].forEach(function (pos, i) {
|
||||
const key = 'c_' + pos;
|
||||
let part = elData(this, key);
|
||||
if (part == null) {
|
||||
if (part === null || part === undefined) { // Does this ever return nullish values?
|
||||
part = document.getElementById(
|
||||
this.attributes['se:connector'].value.split(' ')[i]
|
||||
);
|
||||
|
@ -178,7 +178,7 @@ export default {
|
|||
elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part]));
|
||||
} else part = document.getElementById(part);
|
||||
parts.push(part);
|
||||
}.bind(this));
|
||||
}, this);
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const cElem = parts[i];
|
||||
|
@ -262,15 +262,15 @@ export default {
|
|||
(function () {
|
||||
const gse = svgCanvas.groupSelectedElements;
|
||||
|
||||
svgCanvas.groupSelectedElements = function () {
|
||||
svgCanvas.groupSelectedElements = function (...args) {
|
||||
svgCanvas.removeFromSelection($(connSel).toArray());
|
||||
return gse.apply(this, arguments);
|
||||
return gse.apply(this, args);
|
||||
};
|
||||
|
||||
const mse = svgCanvas.moveSelectedElements;
|
||||
|
||||
svgCanvas.moveSelectedElements = function () {
|
||||
const cmd = mse.apply(this, arguments);
|
||||
svgCanvas.moveSelectedElements = function (...args) {
|
||||
const cmd = mse.apply(this, args);
|
||||
updateConnectors();
|
||||
return cmd;
|
||||
};
|
||||
|
@ -331,7 +331,7 @@ export default {
|
|||
buttons: strings.buttons.map((button, i) => {
|
||||
return Object.assign(buttons[i], button);
|
||||
}),
|
||||
async addLangData ({lang, importLocale}) {
|
||||
/* async */ addLangData ({lang, importLocale}) {
|
||||
return {
|
||||
data: strings.langList
|
||||
};
|
||||
|
@ -548,8 +548,8 @@ export default {
|
|||
const end = elem.getAttribute('marker-end');
|
||||
curLine = elem;
|
||||
$(elem)
|
||||
.data('start_off', !!start)
|
||||
.data('end_off', !!end);
|
||||
.data('start_off', Boolean(start))
|
||||
.data('end_off', Boolean(end));
|
||||
|
||||
if (elem.tagName === 'line' && mid) {
|
||||
// Convert to polyline to accept mid-arrow
|
||||
|
|
|
@ -16,7 +16,7 @@ export default {
|
|||
// https://code.google.com/p/chromium/issues/detail?id=565120.
|
||||
if (isChrome()) {
|
||||
const verIndex = navigator.userAgent.indexOf('Chrome/') + 7;
|
||||
const chromeVersion = parseInt(navigator.userAgent.substring(verIndex), 10);
|
||||
const chromeVersion = parseInt(navigator.userAgent.substring(verIndex));
|
||||
if (chromeVersion < 49) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export default {
|
|||
* @throws {Error} Unexpected event type
|
||||
* @returns {undefined}
|
||||
*/
|
||||
(win, {data, origin}) => {
|
||||
(win, {data, origin}) => { // eslint-disable-line no-shadow
|
||||
// console.log('data, origin', data, origin);
|
||||
let type, content;
|
||||
try {
|
||||
|
@ -78,17 +78,18 @@ export default {
|
|||
if (!pathID) { // Not ready yet as haven't received first payload
|
||||
return;
|
||||
}
|
||||
window.postMessage({
|
||||
webappfind: {
|
||||
type: saveMessage,
|
||||
pathID,
|
||||
content: svgEditor.canvas.getSvgString()
|
||||
}
|
||||
}, window.location.origin === 'null'
|
||||
// Avoid "null" string error for `file:` protocol (even
|
||||
// though file protocol not currently supported by add-on)
|
||||
? '*'
|
||||
: window.location.origin
|
||||
window.postMessage(
|
||||
{
|
||||
webappfind: {
|
||||
type: saveMessage,
|
||||
pathID,
|
||||
content: svgEditor.canvas.getSvgString()
|
||||
}
|
||||
}, window.location.origin === 'null'
|
||||
// Avoid "null" string error for `file:` protocol (even
|
||||
// though file protocol not currently supported by add-on)
|
||||
? '*'
|
||||
: window.location.origin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
import {jml, body, nbsp} from '../../external/jamilih/jml-es.js';
|
||||
|
||||
import $ from '../../external/query-result/esm/index.js';
|
||||
import {manipulation} from '../../external/qr-manipulation/dist/index-es.js';
|
||||
|
||||
manipulation($, jml);
|
||||
|
||||
const baseAPIURL = 'https://openclipart.org/search/json/';
|
||||
|
||||
/**
|
||||
* Shows results after query submission.
|
||||
* @param {string} url
|
||||
* @returns {undefined}
|
||||
*/
|
||||
async function processResults (url) {
|
||||
/**
|
||||
* @param {string} query
|
||||
* @returns {external:JamilihArray}
|
||||
*/
|
||||
function queryLink (query) {
|
||||
return ['a', {
|
||||
href: 'javascript: void(0);',
|
||||
|
@ -22,7 +31,7 @@ async function processResults (url) {
|
|||
|
||||
const r = await fetch(url);
|
||||
const json = await r.json();
|
||||
console.log('json', json);
|
||||
// console.log('json', json);
|
||||
|
||||
if (!json || json.msg !== 'success') {
|
||||
alert('There was a problem downloading the results');
|
||||
|
@ -74,7 +83,7 @@ async function processResults (url) {
|
|||
async click (e) {
|
||||
e.preventDefault();
|
||||
const {value: svgURL, id} = this.dataset;
|
||||
console.log('this', id, svgURL);
|
||||
// console.log('this', id, svgURL);
|
||||
const post = (message) => {
|
||||
// Todo: Make origin customizable as set by opening window
|
||||
// Todo: If dropping IE9, avoid stringifying
|
||||
|
@ -90,7 +99,7 @@ async function processResults (url) {
|
|||
});
|
||||
const result = await fetch(svgURL);
|
||||
const svg = await result.text();
|
||||
console.log('h', svgURL, svg);
|
||||
// console.log('url and svg', svgURL, svg);
|
||||
post({
|
||||
href: svgURL,
|
||||
data: svg
|
||||
|
|
|
@ -5,12 +5,23 @@
|
|||
* @module importModule
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts a possible relative URL into an absolute one.
|
||||
* @param {string} url
|
||||
* @returns {string}
|
||||
*/
|
||||
function toAbsoluteURL (url) {
|
||||
const a = document.createElement('a');
|
||||
a.setAttribute('href', url); // <a href="hoge.html">
|
||||
return a.cloneNode(false).href; // -> "http://example.com/hoge.html"
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any of the whitelisted attributes to the script tag.
|
||||
* @param {HTMLScriptElement} script
|
||||
* @param {PlainObject.<string, string>} atts
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function addScriptAtts (script, atts) {
|
||||
['id', 'class', 'type'].forEach((prop) => {
|
||||
if (prop in atts) {
|
||||
|
@ -27,18 +38,19 @@ function addScriptAtts (script, atts) {
|
|||
*/
|
||||
/**
|
||||
* @function module:importModule.importSetGlobalDefault
|
||||
* @param {string} url
|
||||
* @param {string|string[]} url
|
||||
* @param {module:importModule.ImportConfig} config
|
||||
* @returns {*} The return depends on the export of the targeted module.
|
||||
* @returns {Promise} The value to which it resolves depends on the export of the targeted module.
|
||||
*/
|
||||
export async function importSetGlobalDefault (url, config) {
|
||||
export function importSetGlobalDefault (url, config) {
|
||||
return importSetGlobal(url, {...config, returnDefault: true});
|
||||
}
|
||||
/**
|
||||
* @function module:importModule.importSetGlobal
|
||||
* @param {string} url
|
||||
* @param {string|string[]} url
|
||||
* @param {module:importModule.ImportConfig} config
|
||||
* @returns {ArbitraryModule|*} The return depends on the export of the targeted module.
|
||||
* @returns {Promise} The promise resolves to either an `ArbitraryModule` or
|
||||
* any other value depends on the export of the targeted module.
|
||||
*/
|
||||
export async function importSetGlobal (url, {global, returnDefault}) {
|
||||
// Todo: Replace calls to this function with `import()` when supported
|
||||
|
@ -51,14 +63,21 @@ export async function importSetGlobal (url, {global, returnDefault}) {
|
|||
await importScript(url);
|
||||
return window[global];
|
||||
}
|
||||
// Addition by Brett
|
||||
/**
|
||||
*
|
||||
* @author Brett Zamir (other items are from `dynamic-import-polyfill`)
|
||||
* @param {string|string[]} url
|
||||
* @param {Object} [atts={}]
|
||||
* @returns {Promise} Resolves to `undefined` or rejects with an `Error` upon a
|
||||
* script loading error
|
||||
*/
|
||||
export function importScript (url, atts = {}) {
|
||||
if (Array.isArray(url)) {
|
||||
return Promise.all(url.map((u) => {
|
||||
return importScript(u, atts);
|
||||
}));
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new
|
||||
const script = document.createElement('script');
|
||||
const destructor = () => {
|
||||
script.onerror = null;
|
||||
|
@ -82,13 +101,22 @@ export function importScript (url, atts = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string|string[]} url
|
||||
* @param {Object} [atts={}]
|
||||
* @param {PlainObject} opts
|
||||
* @param {boolean} [opts.returnDefault=false} = {}]
|
||||
* @returns {Promise} Resolves to value of loading module or rejects with
|
||||
* `Error` upon a script loading error.
|
||||
*/
|
||||
export function importModule (url, atts = {}, {returnDefault = false} = {}) {
|
||||
if (Array.isArray(url)) {
|
||||
return Promise.all(url.map((u) => {
|
||||
return importModule(u, atts);
|
||||
}));
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line promise/avoid-new
|
||||
const vector = '$importModule$' + Math.random().toString(32).slice(2);
|
||||
const script = document.createElement('script');
|
||||
const destructor = () => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @copyright 2010 Jeff Schiller
|
||||
*/
|
||||
|
||||
import {getHref, setHref, getRotationAngle} from './utilities.js';
|
||||
import {getHref, setHref, getRotationAngle, isNullish} from './utilities.js';
|
||||
import {removeElementFromListMap} from './svgtransformlist.js';
|
||||
|
||||
/**
|
||||
|
@ -285,9 +285,9 @@ export class RemoveElementCommand extends Command {
|
|||
}
|
||||
|
||||
removeElementFromListMap(this.elem);
|
||||
if (this.nextSibling == null) {
|
||||
if (isNullish(this.nextSibling)) {
|
||||
if (window.console) {
|
||||
console.log('Error: reference element was lost');
|
||||
console.log('Error: reference element was lost'); // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
this.parent.insertBefore(this.elem, this.nextSibling); // Don't use `before` or `prepend` as `this.nextSibling` may be `null`
|
||||
|
@ -670,7 +670,7 @@ export class UndoManager {
|
|||
const oldValues = new Array(i), elements = new Array(i);
|
||||
while (i--) {
|
||||
const elem = elems[i];
|
||||
if (elem == null) { continue; }
|
||||
if (isNullish(elem)) { continue; }
|
||||
elements[i] = elem;
|
||||
oldValues[i] = elem.getAttribute(attrName);
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ export class UndoManager {
|
|||
let i = changeset.elements.length;
|
||||
while (i--) {
|
||||
const elem = changeset.elements[i];
|
||||
if (elem == null) { continue; }
|
||||
if (isNullish(elem)) { continue; }
|
||||
const changes = {};
|
||||
changes[attrName] = changeset.oldValues[i];
|
||||
if (changes[attrName] !== elem.getAttribute(attrName)) {
|
||||
|
|
|
@ -77,8 +77,8 @@ class HistoryRecordingService {
|
|||
if (this.currentBatchCommand_) {
|
||||
const batchCommand = this.currentBatchCommand_;
|
||||
this.batchCommandStack_.pop();
|
||||
const {length} = this.batchCommandStack_;
|
||||
this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null;
|
||||
const {length: len} = this.batchCommandStack_;
|
||||
this.currentBatchCommand_ = len ? this.batchCommandStack_[len - 1] : null;
|
||||
this.addCommand_(batchCommand);
|
||||
}
|
||||
return this;
|
||||
|
@ -141,7 +141,7 @@ class HistoryRecordingService {
|
|||
* Private function to add a command to the history or current batch command.
|
||||
* @private
|
||||
* @param {Command} cmd
|
||||
* @returns {module:history.HistoryRecordingService}
|
||||
* @returns {module:history.HistoryRecordingService|undefined}
|
||||
*/
|
||||
addCommand_ (cmd) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
|
@ -150,6 +150,7 @@ class HistoryRecordingService {
|
|||
} else {
|
||||
this.undoManager_.addCommandToHistory(cmd);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* @param {external:jQuery} $ The jQuery object to which to add the plug-in
|
||||
* @returns {external:jQuery}
|
||||
*/
|
||||
export default function ($) {
|
||||
export default function jQueryPluginSVG ($) {
|
||||
const proxied = $.fn.attr,
|
||||
svgns = 'http://www.w3.org/2000/svg';
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ export default function ($) {
|
|||
*/
|
||||
$.fn.attr = function (key, value) {
|
||||
const len = this.length;
|
||||
if (!len) { return proxied.apply(this, arguments); }
|
||||
if (!len) { return proxied.call(this, key, value); }
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const elem = this[i];
|
||||
// set/get SVG attribute
|
||||
|
@ -70,7 +70,7 @@ export default function ($) {
|
|||
return attr;
|
||||
}
|
||||
} else {
|
||||
return proxied.apply(this, arguments);
|
||||
return proxied.call(this, key, value);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -407,7 +407,8 @@ export default function ($) {
|
|||
'<div class="jGraduate_OkCancel">' +
|
||||
'<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' +
|
||||
'<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' +
|
||||
'</div>');
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// --------------
|
||||
// Set up all the SVG elements (the gradient, stops and rectangle)
|
||||
|
@ -1234,7 +1235,7 @@ export default function ($) {
|
|||
const sm = spreadMethodOpt.val();
|
||||
curGradient.setAttribute('spreadMethod', sm);
|
||||
}
|
||||
showFocus = type === 'rg' && curGradient.getAttribute('fx') != null && !(cx === fx && cy === fy);
|
||||
showFocus = type === 'rg' && curGradient.getAttribute('fx') !== null && !(cx === fx && cy === fy);
|
||||
$('#' + id + '_jGraduate_focusCoord').toggle(showFocus);
|
||||
if (showFocus) {
|
||||
$('#' + id + '_jGraduate_match_ctr')[0].checked = false;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -106,7 +106,7 @@ const svgElementToPdf = function (element, pdf, options) {
|
|||
pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b);
|
||||
}
|
||||
if (attributeIsNotEmpty(node, 'stroke-width')) {
|
||||
pdf.setLineWidth(k * parseInt(node.getAttribute('stroke-width'), 10));
|
||||
pdf.setLineWidth(k * parseInt(node.getAttribute('stroke-width')));
|
||||
}
|
||||
const strokeColor = node.getAttribute('stroke');
|
||||
if (attributeIsNotEmpty(strokeColor)) {
|
||||
|
@ -134,38 +134,38 @@ const svgElementToPdf = function (element, pdf, options) {
|
|||
break;
|
||||
case 'line':
|
||||
pdf.line(
|
||||
k * parseInt(node.getAttribute('x1'), 10),
|
||||
k * parseInt(node.getAttribute('y1'), 10),
|
||||
k * parseInt(node.getAttribute('x2'), 10),
|
||||
k * parseInt(node.getAttribute('y2'), 10)
|
||||
k * parseInt(node.getAttribute('x1')),
|
||||
k * parseInt(node.getAttribute('y1')),
|
||||
k * parseInt(node.getAttribute('x2')),
|
||||
k * parseInt(node.getAttribute('y2'))
|
||||
);
|
||||
removeAttributes(node, pdfSvgAttr.line);
|
||||
break;
|
||||
case 'rect':
|
||||
pdf.rect(
|
||||
k * parseInt(node.getAttribute('x'), 10),
|
||||
k * parseInt(node.getAttribute('y'), 10),
|
||||
k * parseInt(node.getAttribute('width'), 10),
|
||||
k * parseInt(node.getAttribute('height'), 10),
|
||||
k * parseInt(node.getAttribute('x')),
|
||||
k * parseInt(node.getAttribute('y')),
|
||||
k * parseInt(node.getAttribute('width')),
|
||||
k * parseInt(node.getAttribute('height')),
|
||||
colorMode
|
||||
);
|
||||
removeAttributes(node, pdfSvgAttr.rect);
|
||||
break;
|
||||
case 'ellipse':
|
||||
pdf.ellipse(
|
||||
k * parseInt(node.getAttribute('cx'), 10),
|
||||
k * parseInt(node.getAttribute('cy'), 10),
|
||||
k * parseInt(node.getAttribute('rx'), 10),
|
||||
k * parseInt(node.getAttribute('ry'), 10),
|
||||
k * parseInt(node.getAttribute('cx')),
|
||||
k * parseInt(node.getAttribute('cy')),
|
||||
k * parseInt(node.getAttribute('rx')),
|
||||
k * parseInt(node.getAttribute('ry')),
|
||||
colorMode
|
||||
);
|
||||
removeAttributes(node, pdfSvgAttr.ellipse);
|
||||
break;
|
||||
case 'circle':
|
||||
pdf.circle(
|
||||
k * parseInt(node.getAttribute('cx'), 10),
|
||||
k * parseInt(node.getAttribute('cy'), 10),
|
||||
k * parseInt(node.getAttribute('r'), 10),
|
||||
k * parseInt(node.getAttribute('cx')),
|
||||
k * parseInt(node.getAttribute('cy')),
|
||||
k * parseInt(node.getAttribute('r')),
|
||||
colorMode
|
||||
);
|
||||
removeAttributes(node, pdfSvgAttr.circle);
|
||||
|
@ -216,7 +216,7 @@ const svgElementToPdf = function (element, pdf, options) {
|
|||
}
|
||||
pdf.setFontType(fontType);
|
||||
const pdfFontSize = node.hasAttribute('font-size')
|
||||
? parseInt(node.getAttribute('font-size'), 10)
|
||||
? parseInt(node.getAttribute('font-size'))
|
||||
: 16;
|
||||
|
||||
const getWidth = (node) => {
|
||||
|
@ -247,8 +247,8 @@ const svgElementToPdf = function (element, pdf, options) {
|
|||
case 'start': break;
|
||||
case 'default': node.setAttribute('text-anchor', 'start'); break;
|
||||
}
|
||||
x = parseInt(node.getAttribute('x'), 10) - xOffset;
|
||||
y = parseInt(node.getAttribute('y'), 10);
|
||||
x = parseInt(node.getAttribute('x')) - xOffset;
|
||||
y = parseInt(node.getAttribute('y'));
|
||||
}
|
||||
// console.log('fontSize:', pdfFontSize, 'text:', node.textContent);
|
||||
pdf.setFontSize(pdfFontSize).text(
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import {NS} from './namespaces.js';
|
||||
import {toXml, walkTree} from './utilities.js';
|
||||
import {toXml, walkTree, isNullish} from './utilities.js';
|
||||
|
||||
const $ = jQuery;
|
||||
|
||||
|
@ -117,7 +117,7 @@ class Layer {
|
|||
*/
|
||||
getOpacity () {
|
||||
const opacity = this.group_.getAttribute('opacity');
|
||||
if (opacity === null || opacity === undefined) {
|
||||
if (isNullish(opacity)) {
|
||||
return 1;
|
||||
}
|
||||
return parseFloat(opacity);
|
||||
|
@ -212,7 +212,7 @@ Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)');
|
|||
*/
|
||||
function addLayerClass (elem) {
|
||||
const classes = elem.getAttribute('class');
|
||||
if (classes === null || classes === undefined || !classes.length) {
|
||||
if (isNullish(classes) || !classes.length) {
|
||||
elem.setAttribute('class', Layer.CLASS_NAME);
|
||||
} else if (!Layer.CLASS_REGEX.test(classes)) {
|
||||
elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'Es sind nicht-gespeicherte Änderungen vorhanden.',
|
||||
enterNewLinkURL: 'Geben Sie die neue URL ein',
|
||||
errorLoadingSVG: 'Fehler: Kann SVG-Daten nicht laden',
|
||||
URLloadFail: 'Kann von dieser URL nicht laden',
|
||||
URLLoadFail: 'Kann von dieser URL nicht laden',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: "Retrieving '%s' ...",
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'Il y a des changements non sauvegardés.',
|
||||
enterNewLinkURL: "Entrez la nouvelle URL de l'hyperlien",
|
||||
errorLoadingSVG: 'Erreur : Impossible de charger les données SVG',
|
||||
URLloadFail: "Impossible de charger l'URL",
|
||||
URLLoadFail: "Impossible de charger l'URL",
|
||||
retrieving: 'Récupération de « %s »…',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\'...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -207,7 +207,7 @@ export default {
|
|||
unsavedChanges: 'Wykryto niezapisane zmiany.',
|
||||
enterNewLinkURL: 'Wpisz nowy adres URL hiperłącza',
|
||||
errorLoadingSVG: 'Błąd: Nie można załadować danych SVG',
|
||||
URLloadFail: 'Nie można załadować z adresu URL',
|
||||
URLLoadFail: 'Nie można załadować z adresu URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -205,7 +205,7 @@ export default {
|
|||
unsavedChanges: 'Existem alterações não salvas.',
|
||||
enterNewLinkURL: 'Insira novo URL do hyperlink',
|
||||
errorLoadingSVG: 'Erro: Impossível carregar dados SVG',
|
||||
URLloadFail: 'Impossível carregar deste URL',
|
||||
URLLoadFail: 'Impossível carregar deste URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -205,7 +205,7 @@ export default {
|
|||
unsavedChanges: 'Sunt schimbări nesalvate.',
|
||||
enterNewLinkURL: 'IntroduAliniere în raport cu ...sceţi noul URL',
|
||||
errorLoadingSVG: 'Eroare: Nu se pot încărca datele SVG',
|
||||
URLloadFail: 'Nu se poate încărca de la URL',
|
||||
URLLoadFail: 'Nu se poate încărca de la URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'Sú tu neuložené zmeny.',
|
||||
enterNewLinkURL: 'Zadajte nové URL odkazu (hyperlink)',
|
||||
errorLoadingSVG: 'Chyba: Nedajú sa načítať SVG data',
|
||||
URLloadFail: 'Nemožno čítať z URL',
|
||||
URLLoadFail: 'Nemožno čítať z URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -205,7 +205,7 @@ export default {
|
|||
unsavedChanges: 'Obstajajo neshranjene spremembe.',
|
||||
enterNewLinkURL: 'Vnesite novo URL povezavo',
|
||||
errorLoadingSVG: 'Napaka: Ne morem naložiti SVG podatkov',
|
||||
URLloadFail: 'Ne morem naložiti z URL',
|
||||
URLLoadFail: 'Ne morem naložiti z URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: '存在未保存的修改.',
|
||||
enterNewLinkURL: '输入新建链接的URL地址',
|
||||
errorLoadingSVG: '错误: 无法加载SVG数据',
|
||||
URLloadFail: '无法从URL中加载',
|
||||
URLLoadFail: '无法从URL中加载',
|
||||
retrieving: '检索 \'%s\'...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
|||
unsavedChanges: 'There are unsaved changes.',
|
||||
enterNewLinkURL: 'Enter the new hyperlink URL',
|
||||
errorLoadingSVG: 'Error: Unable to load SVG data',
|
||||
URLloadFail: 'Unable to load from URL',
|
||||
URLLoadFail: 'Unable to load from URL',
|
||||
retrieving: 'Retrieving \'%s\' ...',
|
||||
popupWindowBlocked: 'Popup window may be blocked by browser',
|
||||
exportNoBlur: 'Blurred elements will appear as un-blurred',
|
||||
|
|
|
@ -223,7 +223,7 @@ export const readLang = async function (langData) {
|
|||
image_width: properties.image_width,
|
||||
layer_delete: layers.del,
|
||||
layer_down: layers.move_down,
|
||||
layer_new: layers['new'],
|
||||
layer_new: layers.new,
|
||||
layer_rename: layers.rename,
|
||||
layer_moreopts: common.more_opts,
|
||||
layer_up: layers.move_up,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
import {NS} from './namespaces.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import {isNullish} from './utilities.js';
|
||||
|
||||
// Constants
|
||||
const NEAR_ZERO = 1e-14;
|
||||
|
@ -151,14 +152,14 @@ export const transformBox = function (l, t, w, h, m) {
|
|||
* @returns {SVGTransform} A single matrix transform object
|
||||
*/
|
||||
export const transformListToTransform = function (tlist, min, max) {
|
||||
if (tlist == null) {
|
||||
if (isNullish(tlist)) {
|
||||
// Or should tlist = null have been prevented before this?
|
||||
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());
|
||||
}
|
||||
min = min || 0;
|
||||
max = max || (tlist.numberOfItems - 1);
|
||||
min = parseInt(min, 10);
|
||||
max = parseInt(max, 10);
|
||||
min = parseInt(min);
|
||||
max = parseInt(max);
|
||||
if (min > max) { const temp = max; max = min; min = temp; }
|
||||
let m = svg.createSVGMatrix();
|
||||
for (let i = min; i <= max; ++i) {
|
||||
|
|
172
editor/path.js
172
editor/path.js
|
@ -18,7 +18,7 @@ import {
|
|||
} from './math.js';
|
||||
import {
|
||||
assignAttributes, getElem, getRotationAngle, getBBox,
|
||||
getRefElem, findDefs, snapToGrid,
|
||||
getRefElem, findDefs, snapToGrid, isNullish,
|
||||
getBBox as utilsGetBBox
|
||||
} from './utilities.js';
|
||||
import {
|
||||
|
@ -77,7 +77,7 @@ export const setLinkControlPoints = function (lcp) {
|
|||
* @type {null|module:path.Path}
|
||||
* @memberof module:path
|
||||
*/
|
||||
export let path = null;
|
||||
export let path = null; // eslint-disable-line import/no-mutable-exports
|
||||
|
||||
let editorContext_ = null;
|
||||
|
||||
|
@ -240,8 +240,10 @@ export const init = function (editorContext) {
|
|||
editorContext_ = editorContext;
|
||||
|
||||
pathFuncs = [0, 'ClosePath'];
|
||||
const pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',
|
||||
'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'];
|
||||
const pathFuncsStrs = [
|
||||
'Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',
|
||||
'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'
|
||||
];
|
||||
$.each(pathFuncsStrs, function (i, s) {
|
||||
pathFuncs.push(s + 'Abs');
|
||||
pathFuncs.push(s + 'Rel');
|
||||
|
@ -299,14 +301,14 @@ export const ptObjToArr = function (type, segItem) {
|
|||
* @returns {module:math.XYObject}
|
||||
*/
|
||||
export const getGripPt = function (seg, altPt) {
|
||||
const {path} = seg;
|
||||
const {path: pth} = seg;
|
||||
let out = {
|
||||
x: altPt ? altPt.x : seg.item.x,
|
||||
y: altPt ? altPt.y : seg.item.y
|
||||
};
|
||||
|
||||
if (path.matrix) {
|
||||
const pt = transformPoint(out.x, out.y, path.matrix);
|
||||
if (pth.matrix) {
|
||||
const pt = transformPoint(out.x, out.y, pth.matrix);
|
||||
out = pt;
|
||||
}
|
||||
|
||||
|
@ -320,17 +322,17 @@ export const getGripPt = function (seg, altPt) {
|
|||
/**
|
||||
* @function module:path.getPointFromGrip
|
||||
* @param {module:math.XYObject} pt
|
||||
* @param {module:path.Path} path
|
||||
* @param {module:path.Path} pth
|
||||
* @returns {module:math.XYObject}
|
||||
*/
|
||||
export const getPointFromGrip = function (pt, path) {
|
||||
export const getPointFromGrip = function (pt, pth) {
|
||||
const out = {
|
||||
x: pt.x,
|
||||
y: pt.y
|
||||
};
|
||||
|
||||
if (path.matrix) {
|
||||
pt = transformPoint(out.x, out.y, path.imatrix);
|
||||
if (pth.matrix) {
|
||||
pt = transformPoint(out.x, out.y, pth.imatrix);
|
||||
out.x = pt.x;
|
||||
out.y = pt.y;
|
||||
}
|
||||
|
@ -400,8 +402,8 @@ export const addPointGrip = function (index, x, y) {
|
|||
export const getGripContainer = function () {
|
||||
let c = getElem('pathpointgrip_container');
|
||||
if (!c) {
|
||||
const parent = getElem('selectorParentGroup');
|
||||
c = parent.appendChild(document.createElementNS(NS.SVG, 'g'));
|
||||
const parentElement = getElem('selectorParentGroup');
|
||||
c = parentElement.appendChild(document.createElementNS(NS.SVG, 'g'));
|
||||
c.id = 'pathpointgrip_container';
|
||||
}
|
||||
return c;
|
||||
|
@ -539,7 +541,7 @@ export const replacePathSeg = function (type, index, pts, elem) {
|
|||
const pth = elem || path.elem;
|
||||
|
||||
const func = 'createSVGPathSeg' + pathFuncs[type];
|
||||
const seg = pth[func].apply(pth, pts);
|
||||
const seg = pth[func](...pts);
|
||||
|
||||
if (supportsPathReplaceItem()) {
|
||||
pth.pathSegList.replaceItem(seg, index);
|
||||
|
@ -600,9 +602,9 @@ export const getSegSelector = function (seg, update) {
|
|||
|
||||
const pts = ptObjToArr(seg.type, seg.item); // , true);
|
||||
for (let i = 0; i < pts.length; i += 2) {
|
||||
const pt = getGripPt(seg, {x: pts[i], y: pts[i + 1]});
|
||||
pts[i] = pt.x;
|
||||
pts[i + 1] = pt.y;
|
||||
const point = getGripPt(seg, {x: pts[i], y: pts[i + 1]});
|
||||
pts[i] = point.x;
|
||||
pts[i + 1] = point.y;
|
||||
}
|
||||
|
||||
replacePathSeg(seg.type, 1, pts, segLine);
|
||||
|
@ -691,7 +693,7 @@ export class Segment {
|
|||
*/
|
||||
showCtrlPts (y) {
|
||||
for (const i in this.ctrlpts) {
|
||||
if (this.ctrlpts.hasOwnProperty(i)) {
|
||||
if ({}.hasOwnProperty.call(this.ctrlpts, i)) {
|
||||
this.ctrlpts[i].setAttribute('display', y ? 'inline' : 'none');
|
||||
}
|
||||
}
|
||||
|
@ -777,7 +779,8 @@ export class Segment {
|
|||
const {item} = this;
|
||||
|
||||
const curPts = this.ctrlpts
|
||||
? [item.x += dx, item.y += dy,
|
||||
? [
|
||||
item.x += dx, item.y += dy,
|
||||
item.x1, item.y1, item.x2 += dx, item.y2 += dy
|
||||
]
|
||||
: [item.x += dx, item.y += dy];
|
||||
|
@ -786,16 +789,18 @@ export class Segment {
|
|||
|
||||
if (this.next && this.next.ctrlpts) {
|
||||
const next = this.next.item;
|
||||
const nextPts = [next.x, next.y,
|
||||
next.x1 += dx, next.y1 += dy, next.x2, next.y2];
|
||||
const nextPts = [
|
||||
next.x, next.y,
|
||||
next.x1 += dx, next.y1 += dy, next.x2, next.y2
|
||||
];
|
||||
replacePathSeg(this.next.type, this.next.index, nextPts);
|
||||
}
|
||||
|
||||
if (this.mate) {
|
||||
// The last point of a closed subpath has a 'mate',
|
||||
// which is the 'M' segment of the subpath
|
||||
const {item} = this.mate;
|
||||
const pts = [item.x += dx, item.y += dy];
|
||||
const {item: itm} = this.mate;
|
||||
const pts = [itm.x += dx, itm.y += dy];
|
||||
replacePathSeg(this.mate.type, this.mate.index, pts);
|
||||
// Has no grip, so does not need 'updating'?
|
||||
}
|
||||
|
@ -826,9 +831,11 @@ export class Segment {
|
|||
item['x' + anum] = pt.x + (pt.x - this.item['x' + num]);
|
||||
item['y' + anum] = pt.y + (pt.y - this.item['y' + num]);
|
||||
|
||||
const pts = [item.x, item.y,
|
||||
const pts = [
|
||||
item.x, item.y,
|
||||
item.x1, item.y1,
|
||||
item.x2, item.y2];
|
||||
item.x2, item.y2
|
||||
];
|
||||
|
||||
replacePathSeg(seg.type, seg.index, pts);
|
||||
seg.update(true);
|
||||
|
@ -845,8 +852,10 @@ export class Segment {
|
|||
item['x' + num] += dx;
|
||||
item['y' + num] += dy;
|
||||
|
||||
const pts = [item.x, item.y,
|
||||
item.x1, item.y1, item.x2, item.y2];
|
||||
const pts = [
|
||||
item.x, item.y,
|
||||
item.x1, item.y1, item.x2, item.y2
|
||||
];
|
||||
|
||||
replacePathSeg(this.type, this.index, pts);
|
||||
this.update(true);
|
||||
|
@ -883,7 +892,7 @@ export class Path {
|
|||
this.elem = elem;
|
||||
this.segs = [];
|
||||
this.selected_pts = [];
|
||||
path = this;
|
||||
path = this; // eslint-disable-line consistent-this
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
@ -941,7 +950,7 @@ export class Path {
|
|||
seg.next.prev = seg;
|
||||
seg.mate = segs[startI];
|
||||
seg.addGrip();
|
||||
if (this.first_seg == null) {
|
||||
if (isNullish(this.first_seg)) {
|
||||
this.first_seg = seg;
|
||||
}
|
||||
} else if (!nextSeg) {
|
||||
|
@ -977,7 +986,7 @@ export class Path {
|
|||
* @callback module:path.PathEachSegCallback
|
||||
* @this module:path.Segment
|
||||
* @param {Integer} i The index of the seg being iterated
|
||||
* @returns {boolean} Will stop execution of `eachSeg` if returns `false`
|
||||
* @returns {boolean|undefined} Will stop execution of `eachSeg` if returns `false`
|
||||
*/
|
||||
/**
|
||||
* @param {module:path.PathEachSegCallback} fn
|
||||
|
@ -1062,29 +1071,6 @@ export class Path {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Integer} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
subpathIsClosed (index) {
|
||||
let closed = false;
|
||||
// Check if subpath is already open
|
||||
path.eachSeg(function (i) {
|
||||
if (i <= index) { return true; }
|
||||
if (this.type === 2) {
|
||||
// Found M first, so open
|
||||
return false;
|
||||
}
|
||||
if (this.type === 1) {
|
||||
// Found Z first, so closed
|
||||
closed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Integer} index
|
||||
* @returns {undefined}
|
||||
|
@ -1235,7 +1221,7 @@ export class Path {
|
|||
*/
|
||||
selectPt (pt, ctrlNum) {
|
||||
this.clearSelection();
|
||||
if (pt == null) {
|
||||
if (isNullish(pt)) {
|
||||
this.eachSeg(function (i) {
|
||||
// 'this' is the segment here.
|
||||
if (this.prev) {
|
||||
|
@ -1312,11 +1298,35 @@ export class Path {
|
|||
grips[i] = seg.ptgrip;
|
||||
}
|
||||
|
||||
const closedSubpath = this.subpathIsClosed(this.selected_pts[0]);
|
||||
const closedSubpath = Path.subpathIsClosed(this.selected_pts[0]);
|
||||
editorContext_.addPtsToSelection({grips, closedSubpath});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Integer} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Path.subpathIsClosed = function (index) {
|
||||
let clsd = false;
|
||||
// Check if subpath is already open
|
||||
path.eachSeg(function (i) {
|
||||
if (i <= index) { return true; }
|
||||
if (this.type === 2) {
|
||||
// Found M first, so open
|
||||
return false;
|
||||
}
|
||||
if (this.type === 1) {
|
||||
// Found Z first, so closed
|
||||
clsd = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return clsd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function module:path.getPath_
|
||||
* @param {SVGPathElement} elem
|
||||
|
@ -1408,7 +1418,7 @@ export const recalcRotatedPath = function () {
|
|||
|
||||
const rvals = getRotVals(seg.x, seg.y),
|
||||
points = [rvals.x, rvals.y];
|
||||
if (seg.x1 != null && seg.x2 != null) {
|
||||
if (!isNullish(seg.x1) && !isNullish(seg.x2)) {
|
||||
const cVals1 = getRotVals(seg.x1, seg.y1);
|
||||
const cVals2 = getRotVals(seg.x2, seg.y2);
|
||||
points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y);
|
||||
|
@ -1492,26 +1502,28 @@ export const reorientGrads = function (elem, m) {
|
|||
* @name module:path.pathMap
|
||||
* @type {GenericArray}
|
||||
*/
|
||||
const pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
||||
const pathMap = [
|
||||
0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'
|
||||
];
|
||||
|
||||
/**
|
||||
* Convert a path to one with only absolute or relative values.
|
||||
* @todo move to pathActions.js
|
||||
* @function module:path.convertPath
|
||||
* @param {SVGPathElement} path - the path to convert
|
||||
* @param {SVGPathElement} pth - the path to convert
|
||||
* @param {boolean} toRel - true of convert to relative
|
||||
* @returns {string}
|
||||
*/
|
||||
export const convertPath = function (path, toRel) {
|
||||
const segList = path.pathSegList;
|
||||
const len = segList.numberOfItems;
|
||||
export const convertPath = function (pth, toRel) {
|
||||
const {pathSegList} = pth;
|
||||
const len = pathSegList.numberOfItems;
|
||||
let curx = 0, cury = 0;
|
||||
let d = '';
|
||||
let lastM = null;
|
||||
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const seg = segList.getItem(i);
|
||||
const seg = pathSegList.getItem(i);
|
||||
// if these properties are not in the segment, set them to zero
|
||||
let x = seg.x || 0,
|
||||
y = seg.y || 0,
|
||||
|
@ -1776,7 +1788,7 @@ export const pathActions = (function () {
|
|||
* @param {Element} mouseTarget
|
||||
* @param {Float} startX
|
||||
* @param {Float} startY
|
||||
* @returns {undefined}
|
||||
* @returns {boolean|undefined}
|
||||
*/
|
||||
mouseDown (evt, mouseTarget, startX, startY) {
|
||||
let id;
|
||||
|
@ -1922,7 +1934,7 @@ export const pathActions = (function () {
|
|||
editorContext_.getMouseTarget(evt)
|
||||
)) {
|
||||
// Clicked outside canvas, so don't make point
|
||||
console.log('Clicked outside canvas');
|
||||
// console.log('Clicked outside canvas');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1967,11 +1979,11 @@ export const pathActions = (function () {
|
|||
// keep = true;
|
||||
}
|
||||
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TODO: Make sure currentPath isn't null at this point
|
||||
if (!path) { return; }
|
||||
if (!path) { return undefined; }
|
||||
|
||||
path.storeD();
|
||||
|
||||
|
@ -1979,7 +1991,7 @@ export const pathActions = (function () {
|
|||
let curPt;
|
||||
if (id.substr(0, 14) === 'pathpointgrip_') {
|
||||
// Select this point
|
||||
curPt = path.cur_pt = parseInt(id.substr(14), 10);
|
||||
curPt = path.cur_pt = parseInt(id.substr(14));
|
||||
path.dragging = [startX, startY];
|
||||
const seg = path.segs[curPt];
|
||||
|
||||
|
@ -2007,7 +2019,7 @@ export const pathActions = (function () {
|
|||
// Start selection box
|
||||
if (!path.dragging) {
|
||||
let rubberBox = editorContext_.getRubberBox();
|
||||
if (rubberBox == null) {
|
||||
if (isNullish(rubberBox)) {
|
||||
rubberBox = editorContext_.setRubberBox(
|
||||
editorContext_.selectorManager.getRubberBandBox()
|
||||
);
|
||||
|
@ -2021,6 +2033,7 @@ export const pathActions = (function () {
|
|||
display: 'inline'
|
||||
}, 100);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
/**
|
||||
* @param {Float} mouseX
|
||||
|
@ -2127,7 +2140,7 @@ export const pathActions = (function () {
|
|||
} else {
|
||||
path.selected_pts = [];
|
||||
path.eachSeg(function (i) {
|
||||
const seg = this;
|
||||
const seg = this; // eslint-disable-line consistent-this
|
||||
if (!seg.next && !seg.prev) { return; }
|
||||
|
||||
// const {item} = seg;
|
||||
|
@ -2150,12 +2163,18 @@ export const pathActions = (function () {
|
|||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @typedef module:path.keepElement
|
||||
* @type {PlainObject}
|
||||
* @property {boolean} keep
|
||||
* @property {Element} element
|
||||
*/
|
||||
/**
|
||||
* @param {Event} evt
|
||||
* @param {Element} element
|
||||
* @param {Float} mouseX
|
||||
* @param {Float} mouseY
|
||||
* @returns {undefined}
|
||||
* @returns {module:path.keepElement|undefined}
|
||||
*/
|
||||
mouseUp (evt, element, mouseX, mouseY) {
|
||||
const drawnPath = editorContext_.getDrawnPath();
|
||||
|
@ -2203,6 +2222,7 @@ export const pathActions = (function () {
|
|||
pathActions.toSelectMode(evt.target);
|
||||
}
|
||||
hasMoved = false;
|
||||
return undefined;
|
||||
},
|
||||
/**
|
||||
* @param {Element} element
|
||||
|
@ -2273,8 +2293,8 @@ export const pathActions = (function () {
|
|||
reorient () {
|
||||
const elem = editorContext_.getSelectedElements()[0];
|
||||
if (!elem) { return; }
|
||||
const angle = getRotationAngle(elem);
|
||||
if (angle === 0) { return; }
|
||||
const angl = getRotationAngle(elem);
|
||||
if (angl === 0) { return; }
|
||||
|
||||
const batchCmd = new BatchCommand('Reorient path');
|
||||
const changes = {
|
||||
|
@ -2321,7 +2341,7 @@ export const pathActions = (function () {
|
|||
* @returns {false|undefined}
|
||||
*/
|
||||
resetOrientation (pth) {
|
||||
if (pth == null || pth.nodeName !== 'path') { return false; }
|
||||
if (isNullish(pth) || pth.nodeName !== 'path') { return false; }
|
||||
const tlist = getTransformList(pth);
|
||||
const m = transformListToTransform(tlist).matrix;
|
||||
tlist.clear();
|
||||
|
@ -2357,6 +2377,7 @@ export const pathActions = (function () {
|
|||
}
|
||||
|
||||
reorientGrads(pth, m);
|
||||
return undefined;
|
||||
},
|
||||
/**
|
||||
* @returns {undefined}
|
||||
|
@ -2449,9 +2470,10 @@ export const pathActions = (function () {
|
|||
openPt = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (openPt == null) {
|
||||
if (isNullish(openPt)) {
|
||||
// Single path, so close last seg
|
||||
openPt = path.segs.length - 1;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
* @license MIT
|
||||
*/
|
||||
|
||||
import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import {NS} from './namespaces.js';
|
||||
import {convertToNum} from './units.js';
|
||||
import {isWebkit} from './browser.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import {getRotationAngle, getHref, getBBox, getRefElem} from './utilities.js';
|
||||
import {getRotationAngle, getHref, getBBox, getRefElem, isNullish} from './utilities.js';
|
||||
import {BatchCommand, ChangeElementCommand} from './history.js';
|
||||
import {remapElement} from './coords.js';
|
||||
import {
|
||||
|
@ -18,7 +18,7 @@ import {
|
|||
hasMatrixTransform
|
||||
} from './math.js';
|
||||
|
||||
const $ = jqPluginSVG(jQuery);
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
|
||||
let context_;
|
||||
|
||||
|
@ -75,7 +75,7 @@ export const updateClipPath = function (attr, tx, ty) {
|
|||
* @returns {Command} Undo command object with the resulting change
|
||||
*/
|
||||
export const recalculateDimensions = function (selected) {
|
||||
if (selected == null) { return null; }
|
||||
if (isNullish(selected)) { return null; }
|
||||
|
||||
// Firefox Issue - 1081
|
||||
if (selected.nodeName === 'svg' && navigator.userAgent.includes('Firefox/20')) {
|
||||
|
@ -154,7 +154,8 @@ export const recalculateDimensions = function (selected) {
|
|||
|
||||
const m = matrixMultiply(
|
||||
tlist.getItem(k - 2).matrix,
|
||||
tlist.getItem(k - 1).matrix);
|
||||
tlist.getItem(k - 1).matrix
|
||||
);
|
||||
mt.setMatrix(m);
|
||||
tlist.removeItem(k - 2);
|
||||
tlist.removeItem(k - 2);
|
||||
|
@ -241,7 +242,7 @@ export const recalculateDimensions = function (selected) {
|
|||
|
||||
// if we haven't created an initial array in polygon/polyline/path, then
|
||||
// make a copy of initial values and include the transform
|
||||
if (initial == null) {
|
||||
if (isNullish(initial)) {
|
||||
initial = $.extend(true, {}, changes);
|
||||
$.each(initial, function (attr, val) {
|
||||
initial[attr] = convertToNum(attr, val);
|
||||
|
@ -795,15 +796,15 @@ export const recalculateDimensions = function (selected) {
|
|||
// translation required to re-center it
|
||||
// Therefore, [Tr] = [M_inv][Rnew_inv][Rold][M]
|
||||
} else if (operation === 3 && angle) {
|
||||
const m = transformListToTransform(tlist).matrix;
|
||||
const {matrix} = transformListToTransform(tlist);
|
||||
const roldt = svgroot.createSVGTransform();
|
||||
roldt.setRotate(angle, oldcenter.x, oldcenter.y);
|
||||
const rold = roldt.matrix;
|
||||
const rnew = svgroot.createSVGTransform();
|
||||
rnew.setRotate(angle, newcenter.x, newcenter.y);
|
||||
const rnewInv = rnew.matrix.inverse();
|
||||
const mInv = m.inverse();
|
||||
const extrat = matrixMultiply(mInv, rnewInv, rold, m);
|
||||
const mInv = matrix.inverse();
|
||||
const extrat = matrixMultiply(mInv, rnewInv, rold, matrix);
|
||||
|
||||
remapElement(selected, changes, extrat);
|
||||
if (angle) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {supportsSvg} from './browser.js';
|
||||
|
||||
if (!supportsSvg()) {
|
||||
window.location = 'browser-not-supported.html';
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ export const sanitizeSvg = function (node) {
|
|||
const attrNsURI = attr.namespaceURI;
|
||||
// Check that an attribute with the correct localName in the correct namespace is on
|
||||
// our whitelist or is a namespace declaration for one of our allowed namespaces
|
||||
if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&
|
||||
if (!({}.hasOwnProperty.call(allowedAttrsNS, attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&
|
||||
!(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) {
|
||||
// TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.
|
||||
// Bypassing the whitelist to allow se: prefixes.
|
||||
|
@ -159,11 +159,12 @@ export const sanitizeSvg = function (node) {
|
|||
switch (attrName) {
|
||||
case 'transform':
|
||||
case 'gradientTransform':
|
||||
case 'patternTransform':
|
||||
case 'patternTransform': {
|
||||
const val = attr.value.replace(/(\d)-/g, '$1 -');
|
||||
node.setAttribute(attrName, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the style attribute, rewrite it in terms of XML presentational attributes
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import {isTouch, isWebkit} from './browser.js'; // , isOpera
|
||||
import {getRotationAngle, getBBox, getStrokedBBox} from './utilities.js';
|
||||
import {getRotationAngle, getBBox, getStrokedBBox, isNullish} from './utilities.js';
|
||||
import {transformListToTransform, transformBox, transformPoint} from './math.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
|
||||
|
@ -88,30 +88,6 @@ export class Selector {
|
|||
this.selectorGroup.setAttribute('display', 'inline');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates cursors for corner grips on rotation so arrows point the right way.
|
||||
* @param {Float} angle - Current rotation angle in degrees
|
||||
* @returns {undefined}
|
||||
*/
|
||||
updateGripCursors (angle) {
|
||||
let dir;
|
||||
const dirArr = [];
|
||||
let steps = Math.round(angle / 45);
|
||||
if (steps < 0) { steps += 8; }
|
||||
for (dir in selectorManager_.selectorGrips) {
|
||||
dirArr.push(dir);
|
||||
}
|
||||
while (steps > 0) {
|
||||
dirArr.push(dirArr.shift());
|
||||
steps--;
|
||||
}
|
||||
let i = 0;
|
||||
for (dir in selectorManager_.selectorGrips) {
|
||||
selectorManager_.selectorGrips[dir].setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the resize grips of this selector.
|
||||
* @param {boolean} show - Indicates whether grips should be shown or not
|
||||
|
@ -124,7 +100,7 @@ export class Selector {
|
|||
this.hasGrips = show;
|
||||
if (elem && show) {
|
||||
this.selectorGroup.append(selectorManager_.selectorGripsGroup);
|
||||
this.updateGripCursors(getRotationAngle(elem));
|
||||
Selector.updateGripCursors(getRotationAngle(elem));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,11 +221,10 @@ export class Selector {
|
|||
e: [nbax + nbaw, nbay + (nbah) / 2],
|
||||
s: [nbax + (nbaw) / 2, nbay + nbah]
|
||||
};
|
||||
for (const dir in this.gripCoords) {
|
||||
const coords = this.gripCoords[dir];
|
||||
Object.entries(this.gripCoords).forEach(([dir, coords]) => {
|
||||
selectedGrips[dir].setAttribute('cx', coords[0]);
|
||||
selectedGrips[dir].setAttribute('cy', coords[1]);
|
||||
}
|
||||
});
|
||||
|
||||
// we want to go 20 pixels in the negative transformed y direction, ignoring scale
|
||||
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);
|
||||
|
@ -262,6 +237,23 @@ export class Selector {
|
|||
// }
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Updates cursors for corner grips on rotation so arrows point the right way.
|
||||
* @param {Float} angle - Current rotation angle in degrees
|
||||
* @returns {undefined}
|
||||
*/
|
||||
Selector.updateGripCursors = function (angle) {
|
||||
const dirArr = Object.keys(selectorManager_.selectorGrips);
|
||||
let steps = Math.round(angle / 45);
|
||||
if (steps < 0) { steps += 8; }
|
||||
while (steps > 0) {
|
||||
dirArr.push(dirArr.shift());
|
||||
steps--;
|
||||
}
|
||||
Object.values(selectorManager_.selectorGrips).forEach((gripElement, i) => {
|
||||
gripElement.setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Manage all selector objects (selection boxes).
|
||||
|
@ -326,7 +318,7 @@ export class SelectorManager {
|
|||
this.rubberBandBox = null;
|
||||
|
||||
// add the corner grips
|
||||
for (const dir in this.selectorGrips) {
|
||||
Object.keys(this.selectorGrips).forEach((dir) => {
|
||||
const grip = svgFactory_.createSVGElement({
|
||||
element: 'circle',
|
||||
attr: {
|
||||
|
@ -346,7 +338,7 @@ export class SelectorManager {
|
|||
$.data(grip, 'dir', dir);
|
||||
$.data(grip, 'type', 'resize');
|
||||
this.selectorGrips[dir] = this.selectorGripsGroup.appendChild(grip);
|
||||
}
|
||||
});
|
||||
|
||||
// add rotator elems
|
||||
this.rotateGripConnector = this.selectorGripsGroup.appendChild(
|
||||
|
@ -420,7 +412,7 @@ export class SelectorManager {
|
|||
* @returns {Selector} The selector based on the given element
|
||||
*/
|
||||
requestSelector (elem, bbox) {
|
||||
if (elem == null) { return null; }
|
||||
if (isNullish(elem)) { return null; }
|
||||
|
||||
const N = this.selectors.length;
|
||||
// If we've already acquired one for this element, return it.
|
||||
|
@ -450,12 +442,12 @@ export class SelectorManager {
|
|||
* @returns {undefined}
|
||||
*/
|
||||
releaseSelector (elem) {
|
||||
if (elem == null) { return; }
|
||||
if (isNullish(elem)) { return; }
|
||||
const N = this.selectors.length,
|
||||
sel = this.selectorMap[elem.id];
|
||||
if (!sel.locked) {
|
||||
// TODO(codedread): Ensure this exists in this module.
|
||||
console.log('WARNING! selector was released but was already unlocked');
|
||||
console.log('WARNING! selector was released but was already unlocked'); // eslint-disable-line no-console
|
||||
}
|
||||
for (let i = 0; i < N; ++i) {
|
||||
if (this.selectors[i] && this.selectors[i] === sel) {
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
* @param {external:jQuery} $ The jQuery object to which to add the plug-in
|
||||
* @returns {external:jQuery}
|
||||
*/
|
||||
export default function ($) {
|
||||
export default function jQueryPluginSpinButton ($) {
|
||||
if (!$.loadingStylesheets) {
|
||||
$.loadingStylesheets = [];
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@ import {importSetGlobalDefault} from './external/dynamic-import-polyfill/importM
|
|||
import SvgCanvas from './svgcanvas.js';
|
||||
import Layer from './layer.js';
|
||||
|
||||
import jqPluginJSHotkeys from './js-hotkeys/jquery.hotkeys.min.js';
|
||||
import jqPluginBBQ from './jquerybbq/jquery.bbq.min.js';
|
||||
import jqPluginSVGIcons from './svgicons/jQuery.svgIcons.js';
|
||||
import jqPluginJGraduate from './jgraduate/jQuery.jGraduate.js';
|
||||
import jqPluginSpinBtn from './spinbtn/jQuery.SpinButton.js';
|
||||
import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import jqPluginContextMenu from './contextmenu/jQuery.contextMenu.js';
|
||||
import jqPluginJPicker from './jgraduate/jQuery.jPicker.js';
|
||||
import jQueryPluginJSHotkeys from './js-hotkeys/jquery.hotkeys.min.js';
|
||||
import jQueryPluginBBQ from './jquerybbq/jquery.bbq.min.js';
|
||||
import jQueryPluginSVGIcons from './svgicons/jQuery.svgIcons.js';
|
||||
import jQueryPluginJGraduate from './jgraduate/jQuery.jGraduate.js';
|
||||
import jQueryPluginSpinButton from './spinbtn/jQuery.SpinButton.js';
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import jQueryPluginContextMenu from './contextmenu/jQuery.contextMenu.js';
|
||||
import jQueryPluginJPicker from './jgraduate/jQuery.jPicker.js';
|
||||
import {
|
||||
readLang, putLocale,
|
||||
setStrings,
|
||||
|
@ -46,9 +46,9 @@ import loadStylesheets from './external/load-stylesheets/index-es.js';
|
|||
const editor = {};
|
||||
|
||||
const $ = [
|
||||
jqPluginJSHotkeys, jqPluginBBQ, jqPluginSVGIcons, jqPluginJGraduate,
|
||||
jqPluginSpinBtn, jqPluginSVG, jqPluginContextMenu, jqPluginJPicker
|
||||
].reduce(($, cb) => cb($), jQuery);
|
||||
jQueryPluginJSHotkeys, jQueryPluginBBQ, jQueryPluginSVGIcons, jQueryPluginJGraduate,
|
||||
jQueryPluginSpinButton, jQueryPluginSVG, jQueryPluginContextMenu, jQueryPluginJPicker
|
||||
].reduce((jq, func) => func(jq), jQuery);
|
||||
|
||||
/*
|
||||
if (!$.loadingStylesheets) {
|
||||
|
@ -337,11 +337,16 @@ function getImportLocale ({defaultLang, defaultName}) {
|
|||
* @param {string} [localeInfo.lang=defaultLang] Defaults to `defaultLang` of {@link module:SVGEditor~getImportLocale}
|
||||
* @returns {Promise} Resolves to {@link module:locale.LocaleStrings}
|
||||
*/
|
||||
return async function importLocale ({name = defaultName, lang = defaultLang} = {}) {
|
||||
async function importLocale (lang) {
|
||||
const url = `${curConfig.extPath}ext-locale/${name}/${lang}.js`;
|
||||
return async function importLocaleDefaulting ({name = defaultName, lang = defaultLang} = {}) {
|
||||
/**
|
||||
*
|
||||
* @param {string} language
|
||||
* @returns {Promise} Resolves to {@link module:locale.LocaleStrings}
|
||||
*/
|
||||
function importLocale (language) {
|
||||
const url = `${curConfig.extPath}ext-locale/${name}/${language}.js`;
|
||||
return importSetGlobalDefault(url, {
|
||||
global: `svgEditorExtensionLocale_${name}_${lang}`
|
||||
global: `svgEditorExtensionLocale_${name}_${language}`
|
||||
});
|
||||
}
|
||||
try {
|
||||
|
@ -360,7 +365,7 @@ function getImportLocale ({defaultLang, defaultName}) {
|
|||
* Store and retrieve preferences.
|
||||
* @param {string} key The preference name to be retrieved or set
|
||||
* @param {string} [val] The value. If the value supplied is missing or falsey, no change to the preference will be made.
|
||||
* @returns {string} If val is missing or falsey, the value of the previously stored preference will be returned.
|
||||
* @returns {string|undefined} If val is missing or falsey, the value of the previously stored preference will be returned.
|
||||
* @todo Can we change setting on the jQuery namespace (onto editor) to avoid conflicts?
|
||||
* @todo Review whether any remaining existing direct references to
|
||||
* getting `curPrefs` can be changed to use `$.pref()` getting to ensure
|
||||
|
@ -377,7 +382,7 @@ $.pref = function (key, val) {
|
|||
* @implements {module:SVGEditor.Prefs}
|
||||
*/
|
||||
editor.curPrefs = curPrefs; // Update exported value
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
return (key in curPrefs) ? curPrefs[key] : defaultPrefs[key];
|
||||
};
|
||||
|
@ -428,22 +433,20 @@ editor.loadContentAndPrefs = function () {
|
|||
}
|
||||
|
||||
// LOAD PREFS
|
||||
for (const key in defaultPrefs) {
|
||||
if (defaultPrefs.hasOwnProperty(key)) { // It's our own config, so we don't need to iterate up the prototype chain
|
||||
const storeKey = 'svg-edit-' + key;
|
||||
if (editor.storage) {
|
||||
const val = editor.storage.getItem(storeKey);
|
||||
if (val) {
|
||||
defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit)
|
||||
}
|
||||
} else if (window.widget) {
|
||||
defaultPrefs[key] = window.widget.preferenceForKey(storeKey);
|
||||
} else {
|
||||
const result = document.cookie.match(new RegExp('(?:^|;\\s*)' + Utils.regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)'));
|
||||
defaultPrefs[key] = result ? decodeURIComponent(result[1]) : '';
|
||||
Object.keys(defaultPrefs).forEach((key) => {
|
||||
const storeKey = 'svg-edit-' + key;
|
||||
if (editor.storage) {
|
||||
const val = editor.storage.getItem(storeKey);
|
||||
if (val) {
|
||||
defaultPrefs[key] = String(val); // Convert to string for FF (.value fails in Webkit)
|
||||
}
|
||||
} else if (window.widget) {
|
||||
defaultPrefs[key] = window.widget.preferenceForKey(storeKey);
|
||||
} else {
|
||||
const result = document.cookie.match(new RegExp('(?:^|;\\s*)' + Utils.regexEscape(encodeURIComponent(storeKey)) + '=([^;]+)'));
|
||||
defaultPrefs[key] = result ? decodeURIComponent(result[1]) : '';
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -476,12 +479,12 @@ editor.setConfig = function (opts, cfgCfg) {
|
|||
}
|
||||
}
|
||||
$.each(opts, function (key, val) {
|
||||
if (opts.hasOwnProperty(key)) {
|
||||
if ({}.hasOwnProperty.call(opts, key)) {
|
||||
// Only allow prefs defined in defaultPrefs
|
||||
if (defaultPrefs.hasOwnProperty(key)) {
|
||||
if ({}.hasOwnProperty.call(defaultPrefs, key)) {
|
||||
if (cfgCfg.overwrite === false && (
|
||||
curConfig.preventAllURLConfig ||
|
||||
curPrefs.hasOwnProperty(key)
|
||||
{}.hasOwnProperty.call(curPrefs, key)
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
@ -502,30 +505,26 @@ editor.setConfig = function (opts, cfgCfg) {
|
|||
}
|
||||
curConfig[key] = curConfig[key].concat(val); // We will handle any dupes later
|
||||
// Only allow other curConfig if defined in defaultConfig
|
||||
} else if (defaultConfig.hasOwnProperty(key)) {
|
||||
} else if ({}.hasOwnProperty.call(defaultConfig, key)) {
|
||||
if (cfgCfg.overwrite === false && (
|
||||
curConfig.preventAllURLConfig ||
|
||||
curConfig.hasOwnProperty(key)
|
||||
{}.hasOwnProperty.call(curConfig, key)
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
// Potentially overwriting of previously set config
|
||||
if (curConfig.hasOwnProperty(key)) {
|
||||
if ({}.hasOwnProperty.call(curConfig, key)) {
|
||||
if (cfgCfg.overwrite === false) {
|
||||
return;
|
||||
}
|
||||
extendOrAdd(curConfig, key, val);
|
||||
} else if (cfgCfg.allowInitialUserOverride === true) {
|
||||
extendOrAdd(defaultConfig, key, val);
|
||||
} else if (defaultConfig[key] && typeof defaultConfig[key] === 'object') {
|
||||
curConfig[key] = {};
|
||||
$.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects
|
||||
} else {
|
||||
if (cfgCfg.allowInitialUserOverride === true) {
|
||||
extendOrAdd(defaultConfig, key, val);
|
||||
} else {
|
||||
if (defaultConfig[key] && typeof defaultConfig[key] === 'object') {
|
||||
curConfig[key] = {};
|
||||
$.extend(true, curConfig[key], val); // Merge properties recursively, e.g., on initFill, initStroke objects
|
||||
} else {
|
||||
curConfig[key] = val;
|
||||
}
|
||||
}
|
||||
curConfig[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -781,7 +780,7 @@ editor.init = function () {
|
|||
curConfig.extensions.map(async (extname) => {
|
||||
const extName = extname.match(/^ext-(.+)\.js/);
|
||||
if (!extName) { // Ensure URL cannot specify some other unintended file in the extPath
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
const url = curConfig.extPath + extname;
|
||||
// Todo: Replace this with `return import(url);` when
|
||||
|
@ -803,12 +802,15 @@ editor.init = function () {
|
|||
const importLocale = getImportLocale({defaultLang: langParam, defaultName: name});
|
||||
return editor.addExtension(name, (init && init.bind(editor)), importLocale);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.error('Extension failed to load: ' + extname + '; ' + err);
|
||||
// Todo: Add config to alert any errors
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
console.error('Extension failed to load: ' + extname + '; ' + err); // eslint-disable-line no-console
|
||||
return undefined;
|
||||
}
|
||||
})
|
||||
);
|
||||
svgCanvas.bind('extensions_added',
|
||||
svgCanvas.bind(
|
||||
'extensions_added',
|
||||
/**
|
||||
* @param {external:Window} win
|
||||
* @param {module:svgcanvas.SvgCanvas#event:extensions_added} data
|
||||
|
@ -888,8 +890,8 @@ editor.init = function () {
|
|||
for (let i = 0; i < 4; i++) {
|
||||
const s = sides[i];
|
||||
let cur = el.data('orig_margin-' + s);
|
||||
if (cur == null) {
|
||||
cur = parseInt(el.css('margin-' + s), 10);
|
||||
if (Utils.isNullish(cur)) {
|
||||
cur = parseInt(el.css('margin-' + s));
|
||||
// Cache the original margin
|
||||
el.data('orig_margin-' + s, cur);
|
||||
}
|
||||
|
@ -1336,8 +1338,14 @@ editor.init = function () {
|
|||
}
|
||||
});
|
||||
|
||||
function getStylesheetPriority (stylesheet) {
|
||||
switch (stylesheet) {
|
||||
/**
|
||||
* Since stylesheets may be added out of order, we indicate the desired order
|
||||
* for defaults and others after them (in an indeterminate order).
|
||||
* @param {string} stylesheetFile
|
||||
* @returns {Integer|PositiveInfinity}
|
||||
*/
|
||||
function getStylesheetPriority (stylesheetFile) {
|
||||
switch (stylesheetFile) {
|
||||
case 'jgraduate/css/jPicker.css':
|
||||
return 1;
|
||||
case 'jgraduate/css/jGraduate.css':
|
||||
|
@ -1366,7 +1374,7 @@ editor.init = function () {
|
|||
stylesheets.splice(idx, 1, ...$.loadingStylesheets);
|
||||
}
|
||||
}
|
||||
loadStylesheets(stylesheets, {acceptErrors: ({stylesheetURL, reject, resolve}) => {
|
||||
loadStylesheets(stylesheets, {acceptErrors ({stylesheetURL, reject, resolve}) {
|
||||
if ($.loadingStylesheets.includes(stylesheetURL)) {
|
||||
reject(new Error(`Missing expected stylesheet: ${stylesheetURL}`));
|
||||
return;
|
||||
|
@ -1387,7 +1395,8 @@ editor.init = function () {
|
|||
document.getElementById('svgcanvas'),
|
||||
curConfig
|
||||
);
|
||||
const palette = [ // Todo: Make into configuration item?
|
||||
const palette = [
|
||||
// Todo: Make into configuration item?
|
||||
'#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff',
|
||||
'#ff0000', '#ff7f00', '#ffff00', '#7fff00',
|
||||
'#00ff00', '#00ff7f', '#00ffff', '#007fff',
|
||||
|
@ -1487,7 +1496,7 @@ editor.init = function () {
|
|||
if (checkbox.tooltip) {
|
||||
label.attr('title', checkbox.tooltip);
|
||||
}
|
||||
chkbx.prop('checked', !!checkbox.checked);
|
||||
chkbx.prop('checked', Boolean(checkbox.checked));
|
||||
div.append($('<div>').append(label));
|
||||
}
|
||||
$.each(opts || [], function (opt, val) {
|
||||
|
@ -1649,7 +1658,7 @@ editor.init = function () {
|
|||
|
||||
editingsource = true;
|
||||
origSource = svgCanvas.getSvgString();
|
||||
$('#save_output_btns').toggle(!!forSaving);
|
||||
$('#save_output_btns').toggle(Boolean(forSaving));
|
||||
$('#tool_source_back').toggle(!forSaving);
|
||||
$('#svg_source_textarea').val(origSource);
|
||||
$('#svg_source_editor').fadeIn();
|
||||
|
@ -1931,7 +1940,7 @@ editor.init = function () {
|
|||
|
||||
// Create multiple canvases when necessary (due to browser limits)
|
||||
if (rulerLen >= limit) {
|
||||
ctxArrNum = parseInt(rulerLen / limit, 10) + 1;
|
||||
ctxArrNum = parseInt(rulerLen / limit) + 1;
|
||||
ctxArr = [];
|
||||
ctxArr[0] = ctx;
|
||||
let copy;
|
||||
|
@ -2078,8 +2087,8 @@ editor.init = function () {
|
|||
|
||||
const ratio = newCanX / oldCanX;
|
||||
|
||||
const scrollX = w / 2 - wOrig / 2;
|
||||
const scrollY = h / 2 - hOrig / 2;
|
||||
const scrollX = w / 2 - wOrig / 2; // eslint-disable-line no-shadow
|
||||
const scrollY = h / 2 - hOrig / 2; // eslint-disable-line no-shadow
|
||||
|
||||
if (!newCtr) {
|
||||
const oldDistX = oldCtr.x - oldCanX;
|
||||
|
@ -2127,39 +2136,35 @@ editor.init = function () {
|
|||
* @returns {undefined}
|
||||
*/
|
||||
const updateToolButtonState = function () {
|
||||
let index, button;
|
||||
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'];
|
||||
|
||||
if (bNoStroke) {
|
||||
for (index in buttonsNeedingStroke) {
|
||||
button = buttonsNeedingStroke[index];
|
||||
if ($(button).hasClass('tool_button_current')) {
|
||||
buttonsNeedingStroke.forEach((btn) => {
|
||||
if ($(btn).hasClass('tool_button_current')) {
|
||||
clickSelect();
|
||||
}
|
||||
$(button).addClass('disabled');
|
||||
}
|
||||
$(btn).addClass('disabled');
|
||||
});
|
||||
} else {
|
||||
for (index in buttonsNeedingStroke) {
|
||||
button = buttonsNeedingStroke[index];
|
||||
$(button).removeClass('disabled');
|
||||
}
|
||||
buttonsNeedingStroke.forEach((btn) => {
|
||||
$(btn).removeClass('disabled');
|
||||
});
|
||||
}
|
||||
|
||||
if (bNoStroke && bNoFill) {
|
||||
for (index in buttonsNeedingFillAndStroke) {
|
||||
button = buttonsNeedingFillAndStroke[index];
|
||||
if ($(button).hasClass('tool_button_current')) {
|
||||
buttonsNeedingFillAndStroke.forEach((btn) => {
|
||||
if ($(btn).hasClass('tool_button_current')) {
|
||||
clickSelect();
|
||||
}
|
||||
$(button).addClass('disabled');
|
||||
}
|
||||
$(btn).addClass('disabled');
|
||||
});
|
||||
} else {
|
||||
for (index in buttonsNeedingFillAndStroke) {
|
||||
button = buttonsNeedingFillAndStroke[index];
|
||||
$(button).removeClass('disabled');
|
||||
}
|
||||
buttonsNeedingFillAndStroke.forEach((btn) => {
|
||||
$(btn).removeClass('disabled');
|
||||
});
|
||||
}
|
||||
|
||||
svgCanvas.runExtensions('toolButtonStateUpdate', /** @type {module:svgcanvas.SvgCanvas#event:ext-toolButtonStateUpdate} */ {
|
||||
|
@ -2186,14 +2191,14 @@ editor.init = function () {
|
|||
// This function also updates the opacity and id elements that are in the context panel
|
||||
const updateToolbar = function () {
|
||||
let i, len;
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
switch (selectedElement.tagName) {
|
||||
case 'use':
|
||||
case 'image':
|
||||
case 'foreignObject':
|
||||
break;
|
||||
case 'g':
|
||||
case 'a':
|
||||
case 'a': {
|
||||
// Look for common styles
|
||||
const childs = selectedElement.getElementsByTagName('*');
|
||||
let gWidth = null;
|
||||
|
@ -2213,7 +2218,7 @@ editor.init = function () {
|
|||
paintBox.stroke.update(true);
|
||||
|
||||
break;
|
||||
default:
|
||||
} default: {
|
||||
paintBox.fill.update(true);
|
||||
paintBox.stroke.update(true);
|
||||
|
||||
|
@ -2232,10 +2237,11 @@ editor.init = function () {
|
|||
setStrokeOpt($('#linecap_' + attr)[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All elements including image and group have opacity
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
const opacPerc = (selectedElement.getAttribute('opacity') || 1.0) * 100;
|
||||
$('#group_opacity').val(opacPerc);
|
||||
$('#opac_slider').slider('option', 'value', opacPerc);
|
||||
|
@ -2250,7 +2256,7 @@ editor.init = function () {
|
|||
const updateContextPanel = function () {
|
||||
let elem = selectedElement;
|
||||
// If element has just been deleted, consider it null
|
||||
if (elem != null && !elem.parentNode) { elem = null; }
|
||||
if (!Utils.isNullish(elem) && !elem.parentNode) { elem = null; }
|
||||
const currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();
|
||||
const currentMode = svgCanvas.getMode();
|
||||
const unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null;
|
||||
|
@ -2260,7 +2266,7 @@ editor.init = function () {
|
|||
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,' +
|
||||
'#ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel,' +
|
||||
' #use_panel, #a_panel').hide();
|
||||
if (elem != null) {
|
||||
if (!Utils.isNullish(elem)) {
|
||||
const elname = elem.nodeName;
|
||||
// If this is a link with no transform and one child, pretend
|
||||
// its child is selected
|
||||
|
@ -2436,7 +2442,7 @@ editor.init = function () {
|
|||
}
|
||||
menuItems[(tagName === 'g' ? 'en' : 'dis') + 'ableContextMenuItems']('#ungroup');
|
||||
menuItems[((tagName === 'g' || !multiselected) ? 'dis' : 'en') + 'ableContextMenuItems']('#group');
|
||||
// if (elem != null)
|
||||
// if (!Utils.isNullish(elem))
|
||||
} else if (multiselected) {
|
||||
$('#multiselected_panel').show();
|
||||
menuItems
|
||||
|
@ -2506,9 +2512,9 @@ editor.init = function () {
|
|||
}
|
||||
const isNode = mode === 'pathedit';
|
||||
// if elems[1] is present, then we have more than one element
|
||||
selectedElement = (elems.length === 1 || elems[1] == null ? elems[0] : null);
|
||||
multiselected = (elems.length >= 2 && elems[1] != null);
|
||||
if (selectedElement != null) {
|
||||
selectedElement = (elems.length === 1 || Utils.isNullish(elems[1]) ? elems[0] : null);
|
||||
multiselected = (elems.length >= 2 && !Utils.isNullish(elems[1]));
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
// unless we're already in always set the mode of the editor to select because
|
||||
// upon creation of a text element the editor is switched into
|
||||
// select mode and this event fires - we need our UI to be in sync
|
||||
|
@ -2516,7 +2522,7 @@ editor.init = function () {
|
|||
if (!isNode) {
|
||||
updateToolbar();
|
||||
}
|
||||
} // if (elem != null)
|
||||
} // if (!Utils.isNullish(elem))
|
||||
|
||||
// Deal with pathedit mode
|
||||
togglePathEditMode(isNode, elems);
|
||||
|
@ -2545,7 +2551,7 @@ editor.init = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
multiselected = (elems.length >= 2 && elems[1] != null);
|
||||
multiselected = (elems.length >= 2 && !Utils.isNullish(elems[1]));
|
||||
// Only updating fields for single elements for now
|
||||
if (!multiselected) {
|
||||
switch (mode) {
|
||||
|
@ -2601,7 +2607,7 @@ editor.init = function () {
|
|||
}
|
||||
// Update selectedElement if element is no longer part of the image.
|
||||
// This occurs for the text elements in Firefox
|
||||
} else if (elem && selectedElement && selectedElement.parentNode == null) {
|
||||
} else if (elem && selectedElement && Utils.isNullish(selectedElement.parentNode)) {
|
||||
// || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
|
||||
selectedElement = elem;
|
||||
}
|
||||
|
@ -2820,7 +2826,7 @@ editor.init = function () {
|
|||
options = tool;
|
||||
} else {
|
||||
// If flyout is selected, allow shift key to iterate through subitems
|
||||
i = parseInt(i, 10);
|
||||
i = parseInt(i);
|
||||
// Use `allHolders` to include both extension `includeWith` and toolbarButtons
|
||||
options = allHolders[opts.parent][i + 1] ||
|
||||
holders[opts.parent][0];
|
||||
|
@ -3048,7 +3054,7 @@ editor.init = function () {
|
|||
let html;
|
||||
// TODO: Allow support for other types, or adding to existing tool
|
||||
switch (tool.type) {
|
||||
case 'tool_button':
|
||||
case 'tool_button': {
|
||||
html = '<div class="tool_button">' + tool.id + '</div>';
|
||||
const div = $(html).appendTo(panel);
|
||||
if (tool.events) {
|
||||
|
@ -3057,7 +3063,7 @@ editor.init = function () {
|
|||
});
|
||||
}
|
||||
break;
|
||||
case 'select':
|
||||
} case 'select': {
|
||||
html = '<label' + contId + '>' +
|
||||
'<select id="' + tool.id + '">';
|
||||
$.each(tool.options, function (val, text) {
|
||||
|
@ -3072,7 +3078,7 @@ editor.init = function () {
|
|||
$(sel).bind(evt, func);
|
||||
});
|
||||
break;
|
||||
case 'button-select':
|
||||
} case 'button-select': {
|
||||
html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">' +
|
||||
'<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>';
|
||||
|
||||
|
@ -3094,7 +3100,7 @@ editor.init = function () {
|
|||
});
|
||||
|
||||
break;
|
||||
case 'input':
|
||||
} case 'input': {
|
||||
html = '<label' + contId + '>' +
|
||||
'<span id="' + tool.id + '_label">' +
|
||||
tool.label + ':</span>' +
|
||||
|
@ -3117,8 +3123,7 @@ editor.init = function () {
|
|||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -3503,11 +3508,11 @@ editor.init = function () {
|
|||
|
||||
const changeRotationAngle = function (ctl) {
|
||||
svgCanvas.setRotationAngle(ctl.value);
|
||||
$('#tool_reorient').toggleClass('disabled', parseInt(ctl.value, 10) === 0);
|
||||
$('#tool_reorient').toggleClass('disabled', parseInt(ctl.value) === 0);
|
||||
};
|
||||
|
||||
const changeOpacity = function (ctl, val) {
|
||||
if (val == null) { val = ctl.value; }
|
||||
if (Utils.isNullish(val)) { val = ctl.value; }
|
||||
$('#group_opacity').val(val);
|
||||
if (!ctl || !ctl.handle) {
|
||||
$('#opac_slider').slider('option', 'value', val);
|
||||
|
@ -3516,7 +3521,7 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
const changeBlur = function (ctl, val, noUndo) {
|
||||
if (val == null) { val = ctl.value; }
|
||||
if (Utils.isNullish(val)) { val = ctl.value; }
|
||||
$('#blur').val(val);
|
||||
let complete = false;
|
||||
if (!ctl || !ctl.handle) {
|
||||
|
@ -3862,7 +3867,7 @@ editor.init = function () {
|
|||
|
||||
editor.addDropDown('#opacity_dropdown', function () {
|
||||
if ($(this).find('div').length) { return; }
|
||||
const perc = parseInt($(this).text().split('%')[0], 10);
|
||||
const perc = parseInt($(this).text().split('%')[0]);
|
||||
changeOpacity(false, perc);
|
||||
}, true);
|
||||
|
||||
|
@ -3947,7 +3952,7 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
$('#svg_editor').find('button, select, input:not(#text)').focus(function () {
|
||||
inp = this;
|
||||
inp = this; // eslint-disable-line consistent-this
|
||||
uiContext = 'toolbars';
|
||||
workarea.mousedown(unfocus);
|
||||
}).blur(function () {
|
||||
|
@ -4053,19 +4058,19 @@ editor.init = function () {
|
|||
// Delete is a contextual tool that only appears in the ribbon if
|
||||
// an element has been selected
|
||||
const deleteSelected = function () {
|
||||
if (selectedElement != null || multiselected) {
|
||||
if (!Utils.isNullish(selectedElement) || multiselected) {
|
||||
svgCanvas.deleteSelectedElements();
|
||||
}
|
||||
};
|
||||
|
||||
const cutSelected = function () {
|
||||
if (selectedElement != null || multiselected) {
|
||||
if (!Utils.isNullish(selectedElement) || multiselected) {
|
||||
svgCanvas.cutSelectedElements();
|
||||
}
|
||||
};
|
||||
|
||||
const copySelected = function () {
|
||||
if (selectedElement != null || multiselected) {
|
||||
if (!Utils.isNullish(selectedElement) || multiselected) {
|
||||
svgCanvas.copySelectedElements();
|
||||
}
|
||||
};
|
||||
|
@ -4078,37 +4083,37 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
const moveToTopSelected = function () {
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
svgCanvas.moveToTopSelectedElement();
|
||||
}
|
||||
};
|
||||
|
||||
const moveToBottomSelected = function () {
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
svgCanvas.moveToBottomSelectedElement();
|
||||
}
|
||||
};
|
||||
|
||||
const moveUpDownSelected = function (dir) {
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
svgCanvas.moveUpDownSelected(dir);
|
||||
}
|
||||
};
|
||||
|
||||
const convertToPath = function () {
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
svgCanvas.convertToPath();
|
||||
}
|
||||
};
|
||||
|
||||
const reorientPath = function () {
|
||||
if (selectedElement != null) {
|
||||
if (!Utils.isNullish(selectedElement)) {
|
||||
path.reorient();
|
||||
}
|
||||
};
|
||||
|
||||
const makeHyperlink = function () {
|
||||
if (selectedElement != null || multiselected) {
|
||||
if (!Utils.isNullish(selectedElement) || multiselected) {
|
||||
$.prompt(uiStrings.notification.enterNewLinkURL, 'http://', function (url) {
|
||||
if (url) { svgCanvas.makeHyperlink(url); }
|
||||
});
|
||||
|
@ -4116,7 +4121,7 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
const moveSelected = function (dx, dy) {
|
||||
if (selectedElement != null || multiselected) {
|
||||
if (!Utils.isNullish(selectedElement) || multiselected) {
|
||||
if (curConfig.gridSnapping) {
|
||||
// Use grid snap value regardless of zoom level
|
||||
const multi = svgCanvas.getZoom() * curConfig.snappingStep;
|
||||
|
@ -4165,7 +4170,7 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
const rotateSelected = function (cw, step) {
|
||||
if (selectedElement == null || multiselected) { return; }
|
||||
if (Utils.isNullish(selectedElement) || multiselected) { return; }
|
||||
if (!cw) { step *= -1; }
|
||||
const angle = parseFloat($('#angle').val()) + step;
|
||||
svgCanvas.setRotationAngle(angle);
|
||||
|
@ -4263,7 +4268,7 @@ editor.init = function () {
|
|||
if (!customExportImage) {
|
||||
openExportWindow();
|
||||
}
|
||||
const quality = parseInt($('#image-slider').val(), 10) / 100;
|
||||
const quality = parseInt($('#image-slider').val()) / 100;
|
||||
/* const results = */ await svgCanvas.rasterExport(imgType, quality, exportWindowName);
|
||||
}
|
||||
}, function () {
|
||||
|
@ -4289,6 +4294,7 @@ editor.init = function () {
|
|||
};
|
||||
|
||||
const clickImport = function () {
|
||||
/* */
|
||||
};
|
||||
|
||||
const clickUndo = function () {
|
||||
|
@ -4710,13 +4716,14 @@ editor.init = function () {
|
|||
fillAttr = (paint[ptype] !== 'none') ? '#' + paint[ptype] : paint[ptype];
|
||||
break;
|
||||
case 'linearGradient':
|
||||
case 'radialGradient':
|
||||
case 'radialGradient': {
|
||||
this.grad.remove();
|
||||
this.grad = this.defs.appendChild(paint[ptype]);
|
||||
const id = this.grad.id = 'gradbox_' + this.type;
|
||||
fillAttr = 'url(#' + id + ')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.rect.setAttribute('fill', fillAttr);
|
||||
this.rect.setAttribute('opacity', opac);
|
||||
|
@ -4992,8 +4999,8 @@ editor.init = function () {
|
|||
const rulerX = $('#ruler_x');
|
||||
$('#sidepanels').width('+=' + delta);
|
||||
$('#layerpanel').width('+=' + delta);
|
||||
rulerX.css('right', parseInt(rulerX.css('right'), 10) + delta);
|
||||
workarea.css('right', parseInt(workarea.css('right'), 10) + delta);
|
||||
rulerX.css('right', parseInt(rulerX.css('right')) + delta);
|
||||
workarea.css('right', parseInt(workarea.css('right')) + delta);
|
||||
svgCanvas.runExtensions('workareaResized');
|
||||
};
|
||||
|
||||
|
@ -5337,10 +5344,10 @@ editor.init = function () {
|
|||
} else {
|
||||
keyval = opts.key;
|
||||
}
|
||||
keyval += '';
|
||||
keyval = String(keyval);
|
||||
|
||||
const {fn} = opts;
|
||||
$.each(keyval.split('/'), function (i, key) {
|
||||
$.each(keyval.split('/'), function (j, key) {
|
||||
$(document).bind('keydown', key, function (e) {
|
||||
fn();
|
||||
if (pd) {
|
||||
|
@ -5369,7 +5376,9 @@ editor.init = function () {
|
|||
// Misc additional actions
|
||||
|
||||
// Make 'return' keypress trigger the change event
|
||||
$('.attr_changer, #image_url').bind('keydown', 'return',
|
||||
$('.attr_changer, #image_url').bind(
|
||||
'keydown',
|
||||
'return',
|
||||
function (evt) {
|
||||
$(this).change();
|
||||
evt.preventDefault();
|
||||
|
@ -5459,7 +5468,7 @@ editor.init = function () {
|
|||
toggleSidePanel();
|
||||
}
|
||||
|
||||
$('#rulers').toggle(!!curConfig.showRulers);
|
||||
$('#rulers').toggle(Boolean(curConfig.showRulers));
|
||||
|
||||
if (curConfig.showRulers) {
|
||||
$('#show_rulers')[0].checked = true;
|
||||
|
@ -5631,6 +5640,7 @@ editor.init = function () {
|
|||
e.returnValue = uiStrings.notification.unsavedChanges; // Firefox needs this when beforeunload set by addEventListener (even though message is not used)
|
||||
return uiStrings.notification.unsavedChanges;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -5702,8 +5712,8 @@ editor.init = function () {
|
|||
let reader;
|
||||
if (file.type.includes('svg')) {
|
||||
reader = new FileReader();
|
||||
reader.onloadend = function (e) {
|
||||
const newElement = svgCanvas.importSvgString(e.target.result, true);
|
||||
reader.onloadend = function (ev) {
|
||||
const newElement = svgCanvas.importSvgString(ev.target.result, true);
|
||||
svgCanvas.ungroupSelectedElement();
|
||||
svgCanvas.ungroupSelectedElement();
|
||||
svgCanvas.groupSelectedElements();
|
||||
|
@ -5761,7 +5771,7 @@ editor.init = function () {
|
|||
workarea[0].addEventListener('drop', importImage);
|
||||
|
||||
const open = $('<input type="file">').click(function () {
|
||||
const f = this;
|
||||
const f = this; // eslint-disable-line consistent-this
|
||||
editor.openPrep(function (ok) {
|
||||
if (!ok) { return; }
|
||||
svgCanvas.clear();
|
||||
|
@ -5976,7 +5986,7 @@ editor.loadFromURL = function (url, opts) {
|
|||
$.ajax({
|
||||
url,
|
||||
dataType: 'text',
|
||||
cache: !!cache,
|
||||
cache: Boolean(cache),
|
||||
beforeSend () {
|
||||
$.process_cancel(uiStrings.notification.loadingImage);
|
||||
},
|
||||
|
@ -6051,7 +6061,7 @@ const messageQueue = [];
|
|||
* @fires module:svgcanvas.SvgCanvas#event:message
|
||||
* @returns {undefined}
|
||||
*/
|
||||
const messageListener = ({data, origin}) => {
|
||||
const messageListener = ({data, origin}) => { // eslint-disable-line no-shadow
|
||||
// console.log('data, origin, extensionsAdded', data, origin, extensionsAdded);
|
||||
const messageObj = {data, origin};
|
||||
if (!extensionsAdded) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Todo: Obtain/adapt latest jsPDF to utilize ES Module for `jsPDF`/avoid global
|
||||
|
||||
import './svgpathseg.js';
|
||||
import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
|
||||
import * as draw from './draw.js';
|
||||
import * as pathModule from './path.js';
|
||||
|
@ -32,9 +32,10 @@ import {
|
|||
getBBoxOfElementAsPath, convertToPath, toXml, encode64, decode64,
|
||||
dataURLToObjectURL, createObjectURL,
|
||||
getVisibleElements, dropXMLInteralSubset,
|
||||
init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible
|
||||
init as utilsInit, getBBox as utilsGetBBox, getStrokedBBoxDefaultVisible,
|
||||
isNullish
|
||||
} from './utilities.js';
|
||||
import * as history from './history.js';
|
||||
import * as hstry from './history.js';
|
||||
import {
|
||||
transformPoint, matrixMultiply, hasMatrixTransform, transformListToTransform,
|
||||
getMatrix, snapToAngle, isIdentity, rectsIntersect, transformBox
|
||||
|
@ -60,24 +61,25 @@ import {
|
|||
} from './recalculate.js';
|
||||
import {
|
||||
getSelectorManager,
|
||||
Selector,
|
||||
init as selectInit
|
||||
} from './select.js';
|
||||
|
||||
const $ = jqPluginSVG(jQuery);
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
const {
|
||||
MoveElementCommand, InsertElementCommand, RemoveElementCommand,
|
||||
ChangeElementCommand, BatchCommand, UndoManager, HistoryEventTypes
|
||||
} = history;
|
||||
} = hstry;
|
||||
|
||||
if (!window.console) {
|
||||
window.console = {};
|
||||
window.console.log = function (str) {};
|
||||
window.console.dir = function (str) {};
|
||||
window.console.log = function (str) { /* */ };
|
||||
window.console.dir = function (str) { /* */ };
|
||||
}
|
||||
|
||||
if (window.opera) {
|
||||
window.console.log = function (str) { window.opera.postError(str); };
|
||||
window.console.dir = function (str) {};
|
||||
window.console.dir = function (str) { /* */ };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +133,7 @@ if (config) {
|
|||
// Array with width/height of canvas
|
||||
const {dimensions} = curConfig;
|
||||
|
||||
const canvas = this;
|
||||
const canvas = this; // eslint-disable-line consistent-this
|
||||
|
||||
// "document" element associated with the container (same as window.document using default svg-editor.js)
|
||||
// NOTE: This is not actually a SVG document, but an HTML document.
|
||||
|
@ -396,7 +398,7 @@ const getSelectedElements = this.getSelectedElems = function () {
|
|||
return selectedElements;
|
||||
};
|
||||
|
||||
const pathActions = pathModule.pathActions;
|
||||
const {pathActions} = pathModule;
|
||||
|
||||
/**
|
||||
* This should actually be an intersection as all interfaces should be met.
|
||||
|
@ -503,8 +505,8 @@ const undoMgr = canvas.undoMgr = new UndoManager({
|
|||
}
|
||||
if (cmdType === InsertElementCommand.type()) {
|
||||
if (isApply) { restoreRefElems(cmd.elem); }
|
||||
} else {
|
||||
if (!isApply) { restoreRefElems(cmd.elem); }
|
||||
} else if (!isApply) {
|
||||
restoreRefElems(cmd.elem);
|
||||
}
|
||||
if (cmd.elem.tagName === 'use') {
|
||||
setUseData(cmd.elem);
|
||||
|
@ -562,7 +564,7 @@ const getCurrentZoom = this.getZoom = function () { return currentZoom; };
|
|||
* @implements {module:path.EditorContext#round}
|
||||
*/
|
||||
const round = this.round = function (val) {
|
||||
return parseInt(val * currentZoom, 10) / currentZoom;
|
||||
return parseInt(val * currentZoom) / currentZoom;
|
||||
};
|
||||
|
||||
selectInit(
|
||||
|
@ -607,12 +609,13 @@ const getId = canvas.getId = function () {
|
|||
* @implements {module:draw.DrawCanvasInit#call|module:path.EditorContext#call}
|
||||
* @param {"selected"|"changed"|"contextset"|"pointsAdded"|"extension_added"|"extensions_added"|"message"|"transition"|"zoomed"|"updateCanvas"|"zoomDone"|"saved"|"exported"|"exportedPDF"|"setnonce"|"unsetnonce"|"cleared"} ev - String with the event name
|
||||
* @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg - Argument to pass through to the callback function.
|
||||
* @returns {undefined}
|
||||
* @returns {module:svgcanvas.EventHandlerReturn|undefined}
|
||||
*/
|
||||
const call = function (ev, arg) {
|
||||
if (events[ev]) {
|
||||
return events[ev](window, arg);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -624,7 +627,7 @@ const call = function (ev, arg) {
|
|||
*/
|
||||
const clearSelection = this.clearSelection = function (noCall) {
|
||||
selectedElements.forEach((elem) => {
|
||||
if (elem == null) {
|
||||
if (isNullish(elem)) {
|
||||
return;
|
||||
}
|
||||
selectorManager.releaseSelector(elem);
|
||||
|
@ -646,7 +649,7 @@ const addToSelection = this.addToSelection = function (elemsToAdd, showGrips) {
|
|||
|
||||
let j = 0;
|
||||
while (j < selectedElements.length) {
|
||||
if (selectedElements[j] == null) {
|
||||
if (isNullish(selectedElements[j])) {
|
||||
break;
|
||||
}
|
||||
++j;
|
||||
|
@ -692,15 +695,16 @@ const addToSelection = this.addToSelection = function (elemsToAdd, showGrips) {
|
|||
|
||||
selectedElements.sort(function (a, b) {
|
||||
if (a && b && a.compareDocumentPosition) {
|
||||
return 3 - (b.compareDocumentPosition(a) & 6);
|
||||
return 3 - (b.compareDocumentPosition(a) & 6); // eslint-disable-line no-bitwise
|
||||
}
|
||||
if (a == null) {
|
||||
if (isNullish(a)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Make sure first elements are not null
|
||||
while (selectedElements[0] == null) {
|
||||
while (isNullish(selectedElements[0])) {
|
||||
selectedElements.shift(0);
|
||||
}
|
||||
};
|
||||
|
@ -717,7 +721,7 @@ const getOpacity = function () {
|
|||
* @implements {module:path.EditorContext#getMouseTarget}
|
||||
*/
|
||||
const getMouseTarget = this.getMouseTarget = function (evt) {
|
||||
if (evt == null) {
|
||||
if (isNullish(evt)) {
|
||||
return null;
|
||||
}
|
||||
let mouseTarget = evt.target;
|
||||
|
@ -881,8 +885,7 @@ $(opacAni).attr({
|
|||
const restoreRefElems = function (elem) {
|
||||
// Look for missing reference elements, restore any found
|
||||
const attrs = $(elem).attr(refAttrs);
|
||||
for (const o in attrs) {
|
||||
const val = attrs[o];
|
||||
Object.values(attrs).forEach((val) => {
|
||||
if (val && val.startsWith('url(')) {
|
||||
const id = getUrlFromAttr(val).substr(1);
|
||||
const ref = getElem(id);
|
||||
|
@ -891,7 +894,7 @@ const restoreRefElems = function (elem) {
|
|||
delete removedElements[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const childs = elem.getElementsByTagName('*');
|
||||
|
||||
|
@ -1158,9 +1161,9 @@ this.addExtension = async function (name, extInitFunc, importLocale) {
|
|||
|
||||
extensions[name] = extObj;
|
||||
return call('extension_added', extObj);
|
||||
} else {
|
||||
console.log('Cannot add extension "' + name + '", an extension by that name already exists.');
|
||||
}
|
||||
console.log('Cannot add extension "' + name + '", an extension by that name already exists.');
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1176,7 +1179,7 @@ this.addExtension = async function (name, extInitFunc, importLocale) {
|
|||
* @returns {Element[]|NodeList} Bbox elements
|
||||
*/
|
||||
const getIntersectionList = this.getIntersectionList = function (rect) {
|
||||
if (rubberBox == null) { return null; }
|
||||
if (isNullish(rubberBox)) { return null; }
|
||||
|
||||
const parent = currentGroup || getCurrentDrawing().getCurrentLayer();
|
||||
|
||||
|
@ -1201,14 +1204,14 @@ const getIntersectionList = this.getIntersectionList = function (rect) {
|
|||
if (!isIE) {
|
||||
if (typeof svgroot.getIntersectionList === 'function') {
|
||||
// Offset the bbox of the rubber box by the offset of the svgcontent element.
|
||||
rubberBBox.x += parseInt(svgcontent.getAttribute('x'), 10);
|
||||
rubberBBox.y += parseInt(svgcontent.getAttribute('y'), 10);
|
||||
rubberBBox.x += parseInt(svgcontent.getAttribute('x'));
|
||||
rubberBBox.y += parseInt(svgcontent.getAttribute('y'));
|
||||
|
||||
resultList = svgroot.getIntersectionList(rubberBBox, parent);
|
||||
}
|
||||
}
|
||||
|
||||
if (resultList == null || typeof resultList.item !== 'function') {
|
||||
if (isNullish(resultList) || typeof resultList.item !== 'function') {
|
||||
resultList = [];
|
||||
|
||||
if (!curBBoxes.length) {
|
||||
|
@ -1385,11 +1388,18 @@ canvas.call = call;
|
|||
* @type {module:svgcanvas.SvgCanvas#event:selected|module:svgcanvas.SvgCanvas#event:changed|module:svgcanvas.SvgCanvas#event:contextset|module:svgcanvas.SvgCanvas#event:pointsAdded|module:svgcanvas.SvgCanvas#event:extension_added|module:svgcanvas.SvgCanvas#event:extensions_added|module:svgcanvas.SvgCanvas#event:message|module:svgcanvas.SvgCanvas#event:transition|module:svgcanvas.SvgCanvas#event:zoomed|module:svgcanvas.SvgCanvas#event:updateCanvas|module:svgcanvas.SvgCanvas#event:saved|module:svgcanvas.SvgCanvas#event:exported|module:svgcanvas.SvgCanvas#event:exportedPDF|module:svgcanvas.SvgCanvas#event:setnonce|module:svgcanvas.SvgCanvas#event:unsetnonce|undefined}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The promise return, if present, resolves to `undefined`
|
||||
* (`extension_added`, `exported`, `saved`)
|
||||
* @typedef {Promise|undefined} module:svgcanvas.EventHandlerReturn
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback module:svgcanvas.EventHandler
|
||||
* @param {external:Window} win
|
||||
* @param {module:svgcanvas.SvgCanvas#event:GenericCanvasEvent} arg
|
||||
* @listens module:svgcanvas.SvgCanvas#event:GenericCanvasEvent
|
||||
* @returns {module:svgcanvas.EventHandlerReturn}
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1503,7 +1513,7 @@ this.setRotationAngle = function (val, preventUndo) {
|
|||
// }
|
||||
const selector = selectorManager.requestSelector(selectedElements[0]);
|
||||
selector.resize();
|
||||
selector.updateGripCursors(val);
|
||||
Selector.updateGripCursors(val);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1574,7 +1584,7 @@ const selectOnly = this.selectOnly = function (elems, showGrips) {
|
|||
* @returns {undefined}
|
||||
*/
|
||||
/* const removeFromSelection = */ this.removeFromSelection = function (elemsToRemove) {
|
||||
if (selectedElements[0] == null) { return; }
|
||||
if (isNullish(selectedElements[0])) { return; }
|
||||
if (!elemsToRemove.length) { return; }
|
||||
|
||||
// find every element and remove it from our array copy
|
||||
|
@ -1732,7 +1742,7 @@ const mouseDown = function (evt) {
|
|||
// if it is a selector grip, then it must be a single element selected,
|
||||
// set the mouseTarget to that and update the mode to rotate/resize
|
||||
|
||||
if (mouseTarget === selectorManager.selectorParentGroup && selectedElements[0] != null) {
|
||||
if (mouseTarget === selectorManager.selectorParentGroup && !isNullish(selectedElements[0])) {
|
||||
const grip = evt.target;
|
||||
const griptype = elData(grip, 'type');
|
||||
// rotating
|
||||
|
@ -1774,7 +1784,7 @@ const mouseDown = function (evt) {
|
|||
// insert a dummy transform so if the element(s) are moved it will have
|
||||
// a transform to use for its translate
|
||||
for (i = 0; i < selectedElements.length; ++i) {
|
||||
if (selectedElements[i] == null) { continue; }
|
||||
if (isNullish(selectedElements[i])) { continue; }
|
||||
const slist = getTransformList(selectedElements[i]);
|
||||
if (slist.numberOfItems) {
|
||||
slist.insertItemBefore(svgroot.createSVGTransform(), 0);
|
||||
|
@ -1786,7 +1796,7 @@ const mouseDown = function (evt) {
|
|||
} else if (!rightClick) {
|
||||
clearSelection();
|
||||
currentMode = 'multiselect';
|
||||
if (rubberBox == null) {
|
||||
if (isNullish(rubberBox)) {
|
||||
rubberBox = selectorManager.getRubberBandBox();
|
||||
}
|
||||
rStartX *= currentZoom;
|
||||
|
@ -1807,7 +1817,7 @@ const mouseDown = function (evt) {
|
|||
break;
|
||||
case 'zoom':
|
||||
started = true;
|
||||
if (rubberBox == null) {
|
||||
if (isNullish(rubberBox)) {
|
||||
rubberBox = selectorManager.getRubberBandBox();
|
||||
}
|
||||
assignAttributes(rubberBox, {
|
||||
|
@ -1818,7 +1828,7 @@ const mouseDown = function (evt) {
|
|||
display: 'inline'
|
||||
}, 100);
|
||||
break;
|
||||
case 'resize':
|
||||
case 'resize': {
|
||||
started = true;
|
||||
startX = x;
|
||||
startY = y;
|
||||
|
@ -1876,7 +1886,7 @@ const mouseDown = function (evt) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'fhellipse':
|
||||
} case 'fhellipse':
|
||||
case 'fhrect':
|
||||
case 'fhpath':
|
||||
start.x = realX;
|
||||
|
@ -1902,7 +1912,7 @@ const mouseDown = function (evt) {
|
|||
freehand.miny = realY;
|
||||
freehand.maxy = realY;
|
||||
break;
|
||||
case 'image':
|
||||
case 'image': {
|
||||
started = true;
|
||||
const newImage = addSVGElementFromJson({
|
||||
element: 'image',
|
||||
|
@ -1919,7 +1929,7 @@ const mouseDown = function (evt) {
|
|||
setHref(newImage, lastGoodImgUrl);
|
||||
preventClickDefault(newImage);
|
||||
break;
|
||||
case 'square':
|
||||
} case 'square':
|
||||
// FIXME: once we create the rect, we lose information that this was a square
|
||||
// (for resizing purposes this could be important)
|
||||
// Fallthrough
|
||||
|
@ -2119,7 +2129,7 @@ const mouseMove = function (evt) {
|
|||
len = selectedElements.length;
|
||||
for (i = 0; i < len; ++i) {
|
||||
selected = selectedElements[i];
|
||||
if (selected == null) { break; }
|
||||
if (isNullish(selected)) { break; }
|
||||
// if (i === 0) {
|
||||
// const box = utilsGetBBox(selected);
|
||||
// selectedBBoxes[i].x = box.x + dx;
|
||||
|
@ -2411,9 +2421,8 @@ const mouseMove = function (evt) {
|
|||
start = {x: end.x, y: end.y};
|
||||
break;
|
||||
// update path stretch line coordinates
|
||||
} case 'path': {
|
||||
}
|
||||
// fall through
|
||||
} case 'path': { // eslint-disable-line no-empty
|
||||
} // fall through
|
||||
case 'pathedit': {
|
||||
x *= currentZoom;
|
||||
y *= currentZoom;
|
||||
|
@ -2545,16 +2554,16 @@ const mouseUp = function (evt) {
|
|||
// intentionally fall-through to select here
|
||||
case 'resize':
|
||||
case 'multiselect':
|
||||
if (rubberBox != null) {
|
||||
if (!isNullish(rubberBox)) {
|
||||
rubberBox.setAttribute('display', 'none');
|
||||
curBBoxes = [];
|
||||
}
|
||||
currentMode = 'select';
|
||||
// Fallthrough
|
||||
case 'select':
|
||||
if (selectedElements[0] != null) {
|
||||
if (!isNullish(selectedElements[0])) {
|
||||
// if we only have one selected element
|
||||
if (selectedElements[1] == null) {
|
||||
if (isNullish(selectedElements[1])) {
|
||||
// set our current stroke/fill properties to the element's
|
||||
const selected = selectedElements[0];
|
||||
switch (selected.tagName) {
|
||||
|
@ -2589,7 +2598,7 @@ const mouseUp = function (evt) {
|
|||
if (realX !== rStartX || realY !== rStartY) {
|
||||
const len = selectedElements.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
if (selectedElements[i] == null) { break; }
|
||||
if (isNullish(selectedElements[i])) { break; }
|
||||
if (!selectedElements[i].firstChild) {
|
||||
// Not needed for groups (incorrectly resizes elems), possibly not needed at all?
|
||||
selectorManager.requestSelector(selectedElements[i]).resize();
|
||||
|
@ -2598,7 +2607,7 @@ const mouseUp = function (evt) {
|
|||
// no change in position/size, so maybe we should move to pathedit
|
||||
} else {
|
||||
t = evt.target;
|
||||
if (selectedElements[0].nodeName === 'path' && selectedElements[1] == null) {
|
||||
if (selectedElements[0].nodeName === 'path' && isNullish(selectedElements[1])) {
|
||||
pathActions.select(selectedElements[0]);
|
||||
// if it was a path
|
||||
// else, if it was selected and this is a shift-click, remove it from selection
|
||||
|
@ -2622,7 +2631,7 @@ const mouseUp = function (evt) {
|
|||
}
|
||||
return;
|
||||
case 'zoom':
|
||||
if (rubberBox != null) {
|
||||
if (!isNullish(rubberBox)) {
|
||||
rubberBox.setAttribute('display', 'none');
|
||||
}
|
||||
const factor = evt.shiftKey ? 0.5 : 2;
|
||||
|
@ -2774,7 +2783,7 @@ const mouseUp = function (evt) {
|
|||
}
|
||||
});
|
||||
|
||||
if (!keep && element != null) {
|
||||
if (!keep && !isNullish(element)) {
|
||||
getCurrentDrawing().releaseId(getId());
|
||||
element.remove();
|
||||
element = null;
|
||||
|
@ -2799,7 +2808,7 @@ const mouseUp = function (evt) {
|
|||
canvas.setMode('select');
|
||||
selectOnly([t], true);
|
||||
}
|
||||
} else if (element != null) {
|
||||
} else if (!isNullish(element)) {
|
||||
/**
|
||||
* @name module:svgcanvas.SvgCanvas#addedNew
|
||||
* @type {boolean}
|
||||
|
@ -2936,8 +2945,8 @@ $(container).bind(
|
|||
|
||||
// content offset from canvas in screen pixels
|
||||
const wOffset = workarea.offset();
|
||||
const wOffsetLeft = wOffset['left'] + rulerwidth;
|
||||
const wOffsetTop = wOffset['top'] + rulerwidth;
|
||||
const wOffsetLeft = wOffset.left + rulerwidth;
|
||||
const wOffsetTop = wOffset.top + rulerwidth;
|
||||
|
||||
const delta = (evt.wheelDelta) ? evt.wheelDelta : (evt.detail) ? -evt.detail : 0;
|
||||
if (!delta) { return; }
|
||||
|
@ -3508,7 +3517,7 @@ const removeUnusedDefElems = this.removeUnusedDefElems = function () {
|
|||
*/
|
||||
this.svgCanvasToString = function () {
|
||||
// keep calling it until there are none to remove
|
||||
while (removeUnusedDefElems() > 0) {}
|
||||
while (removeUnusedDefElems() > 0) {} // eslint-disable-line no-empty
|
||||
|
||||
pathActions.clear(true);
|
||||
|
||||
|
@ -3572,7 +3581,9 @@ this.svgToString = function (elem, indent) {
|
|||
const attrs = Array.from(elem.attributes);
|
||||
let i;
|
||||
const childs = elem.childNodes;
|
||||
attrs.sort((a, b) => a.name > b.name ? -1 : 1);
|
||||
attrs.sort((a, b) => {
|
||||
return a.name > b.name ? -1 : 1;
|
||||
});
|
||||
|
||||
for (i = 0; i < indent; i++) { out.push(' '); }
|
||||
out.push('<'); out.push(elem.nodeName);
|
||||
|
@ -3693,14 +3704,14 @@ this.svgToString = function (elem, indent) {
|
|||
out.push('\n');
|
||||
out.push(this.svgToString(childs.item(i), indent));
|
||||
break;
|
||||
case 3: // text node
|
||||
case 3: { // text node
|
||||
const str = child.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
if (str !== '') {
|
||||
bOneLine = true;
|
||||
out.push(String(toXml(str)));
|
||||
}
|
||||
break;
|
||||
case 4: // cdata node
|
||||
} case 4: // cdata node
|
||||
out.push('\n');
|
||||
out.push(new Array(indent + 1).join(' '));
|
||||
out.push('<![CDATA[');
|
||||
|
@ -4308,8 +4319,8 @@ const convertToGroup = this.convertToGroup = function (elem) {
|
|||
|
||||
if (vb) {
|
||||
const nums = vb.split(' ');
|
||||
pos.x -= +nums[0];
|
||||
pos.y -= +nums[1];
|
||||
pos.x -= Number(nums[0]);
|
||||
pos.y -= Number(nums[1]);
|
||||
}
|
||||
|
||||
// Not ideal, but works
|
||||
|
@ -4635,12 +4646,12 @@ this.importSvgString = function (xmlString) {
|
|||
// if no explicit viewbox, create one out of the width and height
|
||||
vb = innervb ? innervb.split(' ') : [0, 0, innerw, innerh];
|
||||
for (j = 0; j < 4; ++j) {
|
||||
vb[j] = +(vb[j]);
|
||||
vb[j] = Number(vb[j]);
|
||||
}
|
||||
|
||||
// TODO: properly handle preserveAspectRatio
|
||||
const // canvasw = +svgcontent.getAttribute('width'),
|
||||
canvash = +svgcontent.getAttribute('height');
|
||||
canvash = Number(svgcontent.getAttribute('height'));
|
||||
// imported content should be 1/3 of the canvas on its largest dimension
|
||||
|
||||
if (innerh > innerw) {
|
||||
|
@ -4864,12 +4875,13 @@ this.setConfig = function (opts) {
|
|||
|
||||
/**
|
||||
* @function module:svgcanvas.SvgCanvas#getTitle
|
||||
* @param {Element} elem
|
||||
* @returns {string|undefined} the current group/SVG's title contents
|
||||
* @param {Element} [elem]
|
||||
* @returns {string|undefined} the current group/SVG's title contents or
|
||||
* `undefined` if no element is passed nd there are no selected elements.
|
||||
*/
|
||||
this.getTitle = function (elem) {
|
||||
elem = elem || selectedElements[0];
|
||||
if (!elem) { return; }
|
||||
if (!elem) { return undefined; }
|
||||
elem = $(elem).data('gsvg') || $(elem).data('symbol') || elem;
|
||||
const childs = elem.childNodes;
|
||||
for (let i = 0; i < childs.length; i++) {
|
||||
|
@ -5088,24 +5100,29 @@ this.setBBoxZoom = function (val, editorW, editorH) {
|
|||
}
|
||||
|
||||
switch (val) {
|
||||
case 'selection':
|
||||
if (!selectedElements[0]) { return; }
|
||||
const selectedElems = $.map(selectedElements, function (n) { if (n) { return n; } });
|
||||
case 'selection': {
|
||||
if (!selectedElements[0]) { return undefined; }
|
||||
const selectedElems = $.map(selectedElements, function (n) {
|
||||
if (n) {
|
||||
return n;
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
bb = getStrokedBBoxDefaultVisible(selectedElems);
|
||||
break;
|
||||
case 'canvas':
|
||||
} case 'canvas': {
|
||||
const res = getResolution();
|
||||
spacer = 0.95;
|
||||
bb = {width: res.w, height: res.h, x: 0, y: 0};
|
||||
break;
|
||||
case 'content':
|
||||
} case 'content':
|
||||
bb = getStrokedBBoxDefaultVisible();
|
||||
break;
|
||||
case 'layer':
|
||||
bb = getStrokedBBoxDefaultVisible(getVisibleElements(getCurrentDrawing().getCurrentLayer()));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
return calcZoom(bb);
|
||||
};
|
||||
|
@ -5262,14 +5279,12 @@ this.setColor = function (type, val, preventUndo) {
|
|||
if (elem) {
|
||||
if (elem.tagName === 'g') {
|
||||
walkTree(elem, addNonG);
|
||||
} else {
|
||||
if (type === 'fill') {
|
||||
if (elem.tagName !== 'polyline' && elem.tagName !== 'line') {
|
||||
elems.push(elem);
|
||||
}
|
||||
} else {
|
||||
} else if (type === 'fill') {
|
||||
if (elem.tagName !== 'polyline' && elem.tagName !== 'line') {
|
||||
elems.push(elem);
|
||||
}
|
||||
} else {
|
||||
elems.push(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5651,14 +5666,12 @@ canvas.setBlurOffsets = function (filter, stdDev) {
|
|||
width: '200%',
|
||||
height: '200%'
|
||||
}, 100);
|
||||
} else {
|
||||
// Removing these attributes hides text in Chrome (see Issue 579)
|
||||
if (!isWebkit()) {
|
||||
// Removing these attributes hides text in Chrome (see Issue 579)
|
||||
} else if (!isWebkit()) {
|
||||
filter.removeAttribute('x');
|
||||
filter.removeAttribute('y');
|
||||
filter.removeAttribute('width');
|
||||
filter.removeAttribute('height');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5739,8 +5752,8 @@ canvas.setBlur = function (val, complete) {
|
|||
this.getBold = function () {
|
||||
// should only have one element selected
|
||||
const selected = selectedElements[0];
|
||||
if (selected != null && selected.tagName === 'text' &&
|
||||
selectedElements[1] == null) {
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
return (selected.getAttribute('font-weight') === 'bold');
|
||||
}
|
||||
return false;
|
||||
|
@ -5754,8 +5767,8 @@ this.getBold = function () {
|
|||
*/
|
||||
this.setBold = function (b) {
|
||||
const selected = selectedElements[0];
|
||||
if (selected != null && selected.tagName === 'text' &&
|
||||
selectedElements[1] == null) {
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
changeSelectedAttribute('font-weight', b ? 'bold' : 'normal');
|
||||
}
|
||||
if (!selectedElements[0].textContent) {
|
||||
|
@ -5770,8 +5783,8 @@ this.setBold = function (b) {
|
|||
*/
|
||||
this.getItalic = function () {
|
||||
const selected = selectedElements[0];
|
||||
if (selected != null && selected.tagName === 'text' &&
|
||||
selectedElements[1] == null) {
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
return (selected.getAttribute('font-style') === 'italic');
|
||||
}
|
||||
return false;
|
||||
|
@ -5785,8 +5798,8 @@ this.getItalic = function () {
|
|||
*/
|
||||
this.setItalic = function (i) {
|
||||
const selected = selectedElements[0];
|
||||
if (selected != null && selected.tagName === 'text' &&
|
||||
selectedElements[1] == null) {
|
||||
if (!isNullish(selected) && selected.tagName === 'text' &&
|
||||
isNullish(selectedElements[1])) {
|
||||
changeSelectedAttribute('font-style', i ? 'italic' : 'normal');
|
||||
}
|
||||
if (!selectedElements[0].textContent) {
|
||||
|
@ -5863,7 +5876,7 @@ this.setFontSize = function (val) {
|
|||
*/
|
||||
this.getText = function () {
|
||||
const selected = selectedElements[0];
|
||||
if (selected == null) { return ''; }
|
||||
if (isNullish(selected)) { return ''; }
|
||||
return selected.textContent;
|
||||
};
|
||||
|
||||
|
@ -5967,7 +5980,7 @@ this.setLinkURL = function (val) {
|
|||
*/
|
||||
this.setRectRadius = function (val) {
|
||||
const selected = selectedElements[0];
|
||||
if (selected != null && selected.tagName === 'rect') {
|
||||
if (!isNullish(selected) && selected.tagName === 'rect') {
|
||||
const r = selected.getAttribute('rx');
|
||||
if (r !== String(val)) {
|
||||
selected.setAttribute('rx', val);
|
||||
|
@ -6023,12 +6036,12 @@ this.setSegType = function (newType) {
|
|||
* Otherwise the resulting path element is returned.
|
||||
*/
|
||||
this.convertToPath = function (elem, getBBox) {
|
||||
if (elem == null) {
|
||||
if (isNullish(elem)) {
|
||||
const elems = selectedElements;
|
||||
$.each(elems, function (i, elem) {
|
||||
if (elem) { canvas.convertToPath(elem); }
|
||||
$.each(elems, function (i, el) {
|
||||
if (el) { canvas.convertToPath(el); }
|
||||
});
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
if (getBBox) {
|
||||
return getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);
|
||||
|
@ -6047,7 +6060,7 @@ this.convertToPath = function (elem, getBBox) {
|
|||
opacity: curShape.opacity,
|
||||
visibility: 'hidden'
|
||||
};
|
||||
return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, history, addCommandToHistory);
|
||||
return convertToPath(elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -6066,11 +6079,11 @@ const changeSelectedAttributeNoUndo = function (attr, newValue, elems) {
|
|||
elems = elems || selectedElements;
|
||||
let i = elems.length;
|
||||
const noXYElems = ['g', 'polyline', 'path'];
|
||||
const goodGAttrs = ['transform', 'opacity', 'filter'];
|
||||
// const goodGAttrs = ['transform', 'opacity', 'filter'];
|
||||
|
||||
while (i--) {
|
||||
let elem = elems[i];
|
||||
if (elem == null) { continue; }
|
||||
if (isNullish(elem)) { continue; }
|
||||
|
||||
// Set x,y vals on elements that don't have them
|
||||
if ((attr === 'x' || attr === 'y') && noXYElems.includes(elem.tagName)) {
|
||||
|
@ -6082,10 +6095,10 @@ const changeSelectedAttributeNoUndo = function (attr, newValue, elems) {
|
|||
}
|
||||
|
||||
// only allow the transform/opacity/filter attribute to change on <g> elements, slightly hacky
|
||||
// TODO: FIXME: This doesn't seem right. Where's the body of this if statement?
|
||||
if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {}
|
||||
// TODO: FIXME: Missing statement body
|
||||
// if (elem.tagName === 'g' && goodGAttrs.includes(attr)) {}
|
||||
let oldval = attr === '#text' ? elem.textContent : elem.getAttribute(attr);
|
||||
if (oldval == null) { oldval = ''; }
|
||||
if (isNullish(oldval)) { oldval = ''; }
|
||||
if (oldval !== String(newValue)) {
|
||||
if (attr === '#text') {
|
||||
// const oldW = utilsGetBBox(elem).width;
|
||||
|
@ -6209,7 +6222,7 @@ this.deleteSelectedElements = function () {
|
|||
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const selected = selectedElements[i];
|
||||
if (selected == null) { break; }
|
||||
if (isNullish(selected)) { break; }
|
||||
|
||||
let parent = selected.parentNode;
|
||||
let t = selected;
|
||||
|
@ -6406,7 +6419,7 @@ this.groupSelectedElements = function (type, urlArg) {
|
|||
let i = selectedElements.length;
|
||||
while (i--) {
|
||||
let elem = selectedElements[i];
|
||||
if (elem == null) { continue; }
|
||||
if (isNullish(elem)) { continue; }
|
||||
|
||||
if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) {
|
||||
elem = elem.parentNode;
|
||||
|
@ -6690,7 +6703,7 @@ this.ungroupSelectedElement = function () {
|
|||
*/
|
||||
this.moveToTopSelectedElement = function () {
|
||||
const [selected] = selectedElements;
|
||||
if (selected != null) {
|
||||
if (!isNullish(selected)) {
|
||||
let t = selected;
|
||||
const oldParent = t.parentNode;
|
||||
const oldNextSibling = t.nextSibling;
|
||||
|
@ -6713,7 +6726,7 @@ this.moveToTopSelectedElement = function () {
|
|||
*/
|
||||
this.moveToBottomSelectedElement = function () {
|
||||
const [selected] = selectedElements;
|
||||
if (selected != null) {
|
||||
if (!isNullish(selected)) {
|
||||
let t = selected;
|
||||
const oldParent = t.parentNode;
|
||||
const oldNextSibling = t.nextSibling;
|
||||
|
@ -6759,9 +6772,9 @@ this.moveUpDownSelected = function (dir) {
|
|||
if (this === selected) {
|
||||
foundCur = true;
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
closest = this;
|
||||
closest = this; // eslint-disable-line consistent-this
|
||||
return false;
|
||||
});
|
||||
if (!closest) { return; }
|
||||
|
@ -6799,7 +6812,7 @@ this.moveSelectedElements = function (dx, dy, undoable) {
|
|||
let i = selectedElements.length;
|
||||
while (i--) {
|
||||
const selected = selectedElements[i];
|
||||
if (selected != null) {
|
||||
if (!isNullish(selected)) {
|
||||
// if (i === 0) {
|
||||
// selectedBBoxes[0] = utilsGetBBox(selected);
|
||||
// }
|
||||
|
@ -6867,7 +6880,7 @@ this.cloneSelectedElements = function (x, y) {
|
|||
selectedElements.sort(sortfunction);
|
||||
for (i = 0; i < len; ++i) {
|
||||
elem = selectedElements[i];
|
||||
if (elem == null) { break; }
|
||||
if (isNullish(elem)) { break; }
|
||||
}
|
||||
// use slice to quickly get the subset of elements we need
|
||||
const copiedElements = selectedElements.slice(0, i);
|
||||
|
@ -6905,7 +6918,7 @@ this.alignSelectedElements = function (type, relativeTo) {
|
|||
miny = Number.MAX_VALUE, maxy = Number.MIN_VALUE;
|
||||
let curwidth = Number.MIN_VALUE, curheight = Number.MIN_VALUE;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
if (selectedElements[i] == null) { break; }
|
||||
if (isNullish(selectedElements[i])) { break; }
|
||||
const elem = selectedElements[i];
|
||||
bboxes[i] = getStrokedBBoxDefaultVisible([elem]);
|
||||
|
||||
|
@ -6958,7 +6971,7 @@ this.alignSelectedElements = function (type, relativeTo) {
|
|||
const dx = new Array(len);
|
||||
const dy = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
if (selectedElements[i] == null) { break; }
|
||||
if (isNullish(selectedElements[i])) { break; }
|
||||
// const elem = selectedElements[i];
|
||||
const bbox = bboxes[i];
|
||||
dx[i] = 0;
|
||||
|
@ -7118,7 +7131,7 @@ this.cycleElement = function (next) {
|
|||
let elem = false;
|
||||
const allElems = getVisibleElements(currentGroup || getCurrentDrawing().getCurrentLayer());
|
||||
if (!allElems.length) { return; }
|
||||
if (curElem == null) {
|
||||
if (isNullish(curElem)) {
|
||||
num = next ? allElems.length - 1 : 0;
|
||||
elem = allElems[num];
|
||||
} else {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Todo: Move to own module (and have it import a modular base64 encoder)
|
||||
import {encode64} from '../utilities.js';
|
||||
/**
|
||||
* SVG Icon Loader 2.0
|
||||
*
|
||||
|
@ -96,18 +98,22 @@ $(function() {
|
|||
* @param {external:jQuery} $ Its keys include all icon IDs and the values, the icon as a jQuery object
|
||||
* @returns {external:jQuery} The enhanced jQuery object
|
||||
*/
|
||||
export default function ($) {
|
||||
export default function jQueryPluginSVGIcons ($) {
|
||||
const svgIcons = {};
|
||||
|
||||
let fixIDs;
|
||||
/**
|
||||
* List 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
|
||||
*/
|
||||
/**
|
||||
* @function external:jQuery.svgIcons
|
||||
* @param {string} file The location of a local SVG or SVGz file
|
||||
* @param {PlainObject} [opts]
|
||||
* @param {Float} [opts.w] The icon widths
|
||||
* @param {Float} [opts.h] The icon heights
|
||||
* @param {PlainObject.<string, string>} [opts.fallback] List of raster images with each
|
||||
key being the SVG icon ID to replace, and the value the image file name
|
||||
* @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,
|
||||
|
@ -132,8 +138,10 @@ export default function ($) {
|
|||
iconW = opts.w || 24,
|
||||
iconH = opts.h || 24;
|
||||
let elems, svgdoc, testImg,
|
||||
iconsMade = false, dataLoaded = false, loadAttempts = 0;
|
||||
const isOpera = !!window.opera,
|
||||
iconsMade = false,
|
||||
dataLoaded = false,
|
||||
loadAttempts = 0;
|
||||
const isOpera = Boolean(window.opera),
|
||||
// ua = navigator.userAgent,
|
||||
// isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')),
|
||||
dataPre = 'data:image/svg+xml;charset=utf-8;base64,';
|
||||
|
@ -169,24 +177,28 @@ export default function ($) {
|
|||
$(function () {
|
||||
useFallback();
|
||||
});
|
||||
} else {
|
||||
if (err.responseText) {
|
||||
svgdoc = parser.parseFromString(err.responseText, 'text/xml');
|
||||
} else if (err.responseText) {
|
||||
svgdoc = parser.parseFromString(err.responseText, 'text/xml');
|
||||
|
||||
if (!svgdoc.childNodes.length) {
|
||||
$(useFallback);
|
||||
}
|
||||
$(function () {
|
||||
getIcons('ajax');
|
||||
});
|
||||
} else {
|
||||
if (!svgdoc.childNodes.length) {
|
||||
$(useFallback);
|
||||
}
|
||||
$(function () {
|
||||
getIcons('ajax');
|
||||
});
|
||||
} else {
|
||||
$(useFallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {"ajax"|0|undefined} evt
|
||||
* @param {boolean} [noWait]
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function getIcons (evt, noWait) {
|
||||
if (evt !== 'ajax') {
|
||||
if (dataLoaded) return;
|
||||
|
@ -231,6 +243,14 @@ export default function ($) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {external:jQuery} target
|
||||
* @param {external:jQuery} icon A wrapped `defs` or Image
|
||||
* @param {string} id SVG icon ID
|
||||
* @param {string} setID
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function setIcon (target, icon, id, setID) {
|
||||
if (isOpera) icon.css('visibility', 'hidden');
|
||||
if (opts.replace) {
|
||||
|
@ -249,6 +269,11 @@ export default function ($) {
|
|||
}
|
||||
|
||||
let holder;
|
||||
/**
|
||||
* @param {external:jQuery} icon A wrapped `defs` or Image
|
||||
* @param {string} id SVG icon ID
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function addIcon (icon, id) {
|
||||
if (opts.id_match === undefined || opts.id_match !== false) {
|
||||
setIcon(holder, icon, id, true);
|
||||
|
@ -256,7 +281,13 @@ export default function ($) {
|
|||
svgIcons[id] = icon;
|
||||
}
|
||||
|
||||
function makeIcons (toImage, fallback) {
|
||||
/**
|
||||
*
|
||||
* @param {boolean} [toImage]
|
||||
* @param {external:jQuery.svgIcons.Fallback} [fallback]
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function makeIcons (toImage = false, fallback) {
|
||||
if (iconsMade) return;
|
||||
if (opts.no_img) toImage = false;
|
||||
|
||||
|
@ -359,13 +390,14 @@ export default function ($) {
|
|||
let idElems;
|
||||
if (isOpera) {
|
||||
idElems = defs.find('*').filter(function () {
|
||||
return !!this.id;
|
||||
return Boolean(this.id);
|
||||
});
|
||||
} else {
|
||||
idElems = defs.find('[id]');
|
||||
}
|
||||
|
||||
const allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length;
|
||||
const allElems = svgEl[0].getElementsByTagName('*'),
|
||||
len = allElems.length;
|
||||
|
||||
idElems.each(function (i) {
|
||||
const {id} = this;
|
||||
|
@ -409,49 +441,20 @@ export default function ($) {
|
|||
return svgEl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function useFallback () {
|
||||
if (file.includes('.svgz')) {
|
||||
const regFile = file.replace('.svgz', '.svg');
|
||||
if (window.console) {
|
||||
console.log('.svgz failed, trying with .svg');
|
||||
console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console
|
||||
}
|
||||
$.svgIcons(regFile, opts);
|
||||
} else if (opts.fallback) {
|
||||
makeIcons(false, opts.fallback);
|
||||
}
|
||||
}
|
||||
|
||||
function encode64 (input) {
|
||||
// base64 strings are 4/3 larger than the original string
|
||||
if (window.btoa) return window.btoa(input);
|
||||
const _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
const output = new Array(Math.floor((input.length + 2) / 3) * 4);
|
||||
|
||||
let i = 0, p = 0;
|
||||
do {
|
||||
const chr1 = input.charCodeAt(i++);
|
||||
const chr2 = input.charCodeAt(i++);
|
||||
const chr3 = input.charCodeAt(i++);
|
||||
|
||||
const enc1 = chr1 >> 2;
|
||||
const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
|
||||
let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
let enc4 = chr3 & 63;
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
||||
output[p++] = _keyStr.charAt(enc1);
|
||||
output[p++] = _keyStr.charAt(enc2);
|
||||
output[p++] = _keyStr.charAt(enc3);
|
||||
output[p++] = _keyStr.charAt(enc4);
|
||||
} while (i < input.length);
|
||||
|
||||
return output.join('');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
* including the latest spec changes which were implemented in Firefox 43 and
|
||||
* Chrome 46.
|
||||
*/
|
||||
/* eslint-disable no-shadow, class-methods-use-this */
|
||||
// Linting: We avoid `no-shadow` as ESLint thinks these are still available globals
|
||||
// Linting: We avoid `class-methods-use-this` as this is a polyfill that must
|
||||
// follow the conventions
|
||||
(() => {
|
||||
if (!('SVGPathSeg' in window)) {
|
||||
// Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
|
||||
|
@ -591,7 +595,7 @@ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.pro
|
|||
return [];
|
||||
}
|
||||
|
||||
const owningPathSegList = this;
|
||||
const owningPathSegList = this; // eslint-disable-line consistent-this
|
||||
|
||||
class Builder {
|
||||
constructor () {
|
||||
|
@ -883,10 +887,10 @@ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.pro
|
|||
} case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: {
|
||||
const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
|
||||
return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
|
||||
} case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
|
||||
} case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: {
|
||||
const points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
|
||||
return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
|
||||
case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
||||
} case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
||||
return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
|
||||
case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
|
||||
return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
|
||||
|
|
|
@ -12,7 +12,11 @@ import {supportsNativeTransformLists} from './browser.js';
|
|||
|
||||
const svgroot = document.createElementNS(NS.SVG, 'svg');
|
||||
|
||||
// Helper function.
|
||||
/**
|
||||
* Helper function to convert `SVGTransform` to a string.
|
||||
* @param {SVGTransform} xform
|
||||
* @returns {string}
|
||||
*/
|
||||
function transformToString (xform) {
|
||||
const m = xform.matrix;
|
||||
let text = '';
|
||||
|
@ -114,8 +118,9 @@ let listMap_ = {};
|
|||
* These methods do not currently raise any exceptions.
|
||||
* These methods also do not check that transforms are being inserted. This is basically
|
||||
* implementing as much of SVGTransformList that we need to get the job done.
|
||||
* @implements {module:SVGTransformList.SVGEditTransformList}
|
||||
*/
|
||||
export class SVGTransformList {
|
||||
export class SVGTransformList {// eslint-disable-line no-shadow
|
||||
/**
|
||||
* @param {Element} elem
|
||||
*/
|
||||
|
@ -170,7 +175,7 @@ export class SVGTransformList {
|
|||
} else if (name === 'rotate' && values.length === 1) {
|
||||
values.push(0, 0);
|
||||
}
|
||||
xform[fname].apply(xform, values);
|
||||
xform[fname](...values);
|
||||
this._list.appendItem(xform);
|
||||
}
|
||||
}
|
||||
|
@ -179,20 +184,15 @@ export class SVGTransformList {
|
|||
if (item) {
|
||||
// Check if this transform is already in a transformlist, and
|
||||
// remove it if so.
|
||||
let found = false;
|
||||
for (const id in listMap_) {
|
||||
const tl = listMap_[id];
|
||||
Object.values(listMap_).some((tl) => {
|
||||
for (let i = 0, len = tl._xforms.length; i < len; ++i) {
|
||||
if (tl._xforms[i] === item) {
|
||||
found = true;
|
||||
tl.removeItem(i);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -330,7 +330,7 @@ export const resetListMap = function () {
|
|||
* @param {Element} elem - a DOM Element
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export let removeElementFromListMap = function (elem) {
|
||||
export let removeElementFromListMap = function (elem) { // eslint-disable-line import/no-mutable-exports
|
||||
if (elem.id && listMap_[elem.id]) {
|
||||
delete listMap_[elem.id];
|
||||
}
|
||||
|
@ -377,6 +377,7 @@ export const getTransformList = function (elem) {
|
|||
* @param {module:SVGTransformList.removeElementFromListMap} cb Passed a single argument `elem`
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export const changeRemoveElementFromListMap = function (cb) {
|
||||
|
||||
export const changeRemoveElementFromListMap = function (cb) { // eslint-disable-line promise/prefer-await-to-callbacks
|
||||
removeElementFromListMap = cb;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
|
||||
/**
|
||||
*
|
||||
* @param {Event} ev
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function touchHandler (ev) {
|
||||
const {changedTouches} = ev,
|
||||
first = changedTouches[0];
|
||||
|
@ -11,7 +16,7 @@ function touchHandler (ev) {
|
|||
default: return;
|
||||
}
|
||||
|
||||
const {screenX, screenY, clientX, clientY} = first;
|
||||
const {screenX, screenY, clientX, clientY} = first; // eslint-disable-line no-shadow
|
||||
const simulatedEvent = new MouseEvent(type, {
|
||||
// Event interface
|
||||
bubbles: true,
|
||||
|
|
|
@ -50,3 +50,12 @@
|
|||
/**
|
||||
* @external Window
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external JamilihArray
|
||||
* @type {GenericArray}
|
||||
* @property {string} 0 Element name
|
||||
* @property {PlainObject<string, string>|JamilihArray} [1] Generally a map from an attribute name to attribute value, but also adds event handlers, etc.
|
||||
* @property {JamilihArray} [2] Children
|
||||
* @see {@link https://github.com/brettz9/jamilih/}
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import {NS} from './namespaces.js';
|
||||
import {isNullish} from './utilities.js';
|
||||
|
||||
const wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];
|
||||
const hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];
|
||||
|
@ -40,7 +41,7 @@ let typeMap_ = {};
|
|||
*/
|
||||
/**
|
||||
* @function module:units.ElementContainer#getElement
|
||||
* @returns {Element} An element in the container given an id
|
||||
* @returns {?Element} An element in the container given an id
|
||||
*/
|
||||
/**
|
||||
* @function module:units.ElementContainer#getHeight
|
||||
|
@ -134,8 +135,7 @@ export const getTypeMap = function () {
|
|||
export const shortFloat = function (val) {
|
||||
const digits = elementContainer_.getRoundDigits();
|
||||
if (!isNaN(val)) {
|
||||
// Note that + converts to Number
|
||||
return +((+val).toFixed(digits));
|
||||
return Number(Number(val).toFixed(digits));
|
||||
}
|
||||
if (Array.isArray(val)) {
|
||||
return shortFloat(val[0]) + ',' + shortFloat(val[1]);
|
||||
|
@ -304,7 +304,7 @@ export const isValidUnit = function (attr, val, selectedElement) {
|
|||
// not already present
|
||||
try {
|
||||
const elem = elementContainer_.getElement(val);
|
||||
result = (elem == null || elem === selectedElement);
|
||||
result = (isNullish(elem) || elem === selectedElement);
|
||||
} catch (e) {}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import './svgpathseg.js';
|
||||
import jqPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import jQueryPluginSVG from './jQuery.attr.js'; // Needed for SVG attribute setting and array form with `attr`
|
||||
import {NS} from './namespaces.js';
|
||||
import {getTransformList} from './svgtransformlist.js';
|
||||
import {setUnitAttr, getTypeMap} from './units.js';
|
||||
|
@ -22,7 +22,7 @@ import {
|
|||
} from './browser.js';
|
||||
|
||||
// Constants
|
||||
const $ = jqPluginSVG(jQuery);
|
||||
const $ = jQueryPluginSVG(jQuery);
|
||||
|
||||
// String used to encode base64.
|
||||
const KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
@ -123,7 +123,12 @@ export const dropXMLInteralSubset = (str) => {
|
|||
export const toXml = function (str) {
|
||||
// ' is ok in XML, but not HTML
|
||||
// > does not normally need escaping, though it can if within a CDATA expression (and preceded by "]]")
|
||||
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '''); // Note: `'` is XML only
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, '''); // Note: `'` is XML only
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -133,9 +138,9 @@ export const toXml = function (str) {
|
|||
* @param {string} str - The string to be converted
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
export const fromXml = function (str) {
|
||||
export function fromXml (str) {
|
||||
return $('<p/>').html(str).text();
|
||||
};
|
||||
}
|
||||
|
||||
// This code was written by Tyler Akins and has been placed in the
|
||||
// public domain. It would be nice if you left this header intact.
|
||||
|
@ -150,30 +155,33 @@ export const fromXml = function (str) {
|
|||
* @param {string} input
|
||||
* @returns {string} Base64 output
|
||||
*/
|
||||
export const encode64 = function (input) {
|
||||
export function encode64 (input) {
|
||||
// base64 strings are 4/3 larger than the original string
|
||||
input = encodeUTF8(input); // convert non-ASCII characters
|
||||
// input = convertToXMLReferences(input);
|
||||
if (window.btoa) {
|
||||
return window.btoa(input); // Use native if available
|
||||
}
|
||||
const output = [];
|
||||
output.length = Math.floor((input.length + 2) / 3) * 4;
|
||||
const output = new Array(Math.floor((input.length + 2) / 3) * 4);
|
||||
|
||||
let i = 0, p = 0;
|
||||
let i = 0,
|
||||
p = 0;
|
||||
do {
|
||||
const chr1 = input.charCodeAt(i++);
|
||||
const chr2 = input.charCodeAt(i++);
|
||||
const chr3 = input.charCodeAt(i++);
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
const enc1 = chr1 >> 2;
|
||||
const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
|
||||
let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
let enc4 = chr3 & 63;
|
||||
/* eslint-enable no-bitwise */
|
||||
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
enc3 = 64;
|
||||
enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
@ -185,7 +193,7 @@ export const encode64 = function (input) {
|
|||
} while (i < input.length);
|
||||
|
||||
return output.join('');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string from base64.
|
||||
|
@ -193,7 +201,7 @@ export const encode64 = function (input) {
|
|||
* @param {string} input Base64-encoded input
|
||||
* @returns {string} Decoded output
|
||||
*/
|
||||
export const decode64 = function (input) {
|
||||
export function decode64 (input) {
|
||||
if (window.atob) {
|
||||
return decodeUTF8(window.atob(input));
|
||||
}
|
||||
|
@ -210,30 +218,32 @@ export const decode64 = function (input) {
|
|||
const enc3 = KEYSTR.indexOf(input.charAt(i++));
|
||||
const enc4 = KEYSTR.indexOf(input.charAt(i++));
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
const chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
const chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
/* eslint-enable no-bitwise */
|
||||
|
||||
output += String.fromCharCode(chr1);
|
||||
|
||||
if (enc3 !== 64) {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
output += String.fromCharCode(chr2);
|
||||
}
|
||||
if (enc4 !== 64) {
|
||||
output = output + String.fromCharCode(chr3);
|
||||
output += String.fromCharCode(chr3);
|
||||
}
|
||||
} while (i < input.length);
|
||||
return decodeUTF8(output);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @function module:utilities.decodeUTF8
|
||||
* @param {string} argString
|
||||
* @returns {string}
|
||||
*/
|
||||
export const decodeUTF8 = function (argString) {
|
||||
export function decodeUTF8 (argString) {
|
||||
return decodeURIComponent(escape(argString));
|
||||
};
|
||||
}
|
||||
|
||||
// codedread:does not seem to work with webkit-based browsers on OSX // Brettz9: please test again as function upgraded
|
||||
/**
|
||||
|
@ -255,7 +265,8 @@ export const dataURLToObjectURL = function (dataurl) {
|
|||
if (typeof Uint8Array === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) {
|
||||
return '';
|
||||
}
|
||||
const arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
|
||||
const arr = dataurl.split(','),
|
||||
mime = arr[0].match(/:(.*?);/)[1],
|
||||
bstr = atob(arr[1]);
|
||||
let n = bstr.length;
|
||||
const u8arr = new Uint8Array(n);
|
||||
|
@ -430,7 +441,7 @@ export const getUrlFromAttr = function (attrVal) {
|
|||
* @param {Element} elem
|
||||
* @returns {string} The given element's `xlink:href` value
|
||||
*/
|
||||
export let getHref = function (elem) {
|
||||
export let getHref = function (elem) { // eslint-disable-line import/no-mutable-exports
|
||||
return elem.getAttributeNS(NS.XLINK, 'href');
|
||||
};
|
||||
|
||||
|
@ -441,7 +452,7 @@ export let getHref = function (elem) {
|
|||
* @param {string} val
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export let setHref = function (elem, val) {
|
||||
export let setHref = function (elem, val) { // eslint-disable-line import/no-mutable-exports
|
||||
elem.setAttributeNS(NS.XLINK, 'xlink:href', val);
|
||||
};
|
||||
|
||||
|
@ -484,6 +495,15 @@ export const getPathBBox = function (path) {
|
|||
const start = seglist.getItem(0);
|
||||
let P0 = [start.x, start.y];
|
||||
|
||||
const getCalc = function (j, P1, P2, P3) {
|
||||
return function (t) {
|
||||
return Math.pow(1 - t, 3) * P0[j] +
|
||||
3 * Math.pow(1 - t, 2) * t * P1[j] +
|
||||
3 * (1 - t) * Math.pow(t, 2) * P2[j] +
|
||||
Math.pow(t, 3) * P3[j];
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < tot; i++) {
|
||||
const seg = seglist.getItem(i);
|
||||
|
||||
|
@ -499,21 +519,14 @@ export const getPathBBox = function (path) {
|
|||
P3 = [seg.x, seg.y];
|
||||
|
||||
for (let j = 0; j < 2; j++) {
|
||||
const calc = function (t) {
|
||||
return Math.pow(1 - t, 3) * P0[j] +
|
||||
3 * Math.pow(1 - t, 2) * t * P1[j] +
|
||||
3 * (1 - t) * Math.pow(t, 2) * P2[j] +
|
||||
Math.pow(t, 3) * P3[j];
|
||||
};
|
||||
const calc = getCalc(j, P1, P2, P3);
|
||||
|
||||
const b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];
|
||||
const a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
|
||||
const c = 3 * P1[j] - 3 * P0[j];
|
||||
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
continue;
|
||||
}
|
||||
if (b === 0) { continue; }
|
||||
const t = -c / b;
|
||||
if (t > 0 && t < 1) {
|
||||
bounds[j].push(calc(t));
|
||||
|
@ -612,15 +625,15 @@ export const getBBox = function (elem) {
|
|||
selected.textContent = 'a'; // Some character needed for the selector to use.
|
||||
ret = selected.getBBox();
|
||||
selected.textContent = '';
|
||||
} else {
|
||||
if (selected.getBBox) { ret = selected.getBBox(); }
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'path':
|
||||
if (!supportsPathBBox()) {
|
||||
ret = getPathBBox(selected);
|
||||
} else {
|
||||
if (selected.getBBox) { ret = selected.getBBox(); }
|
||||
} else if (selected.getBBox) {
|
||||
ret = selected.getBBox();
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
|
@ -719,12 +732,13 @@ export const getPathDFromElement = function (elem) {
|
|||
let d, a, rx, ry;
|
||||
switch (elem.tagName) {
|
||||
case 'ellipse':
|
||||
case 'circle':
|
||||
case 'circle': {
|
||||
a = $(elem).attr(['rx', 'ry', 'cx', 'cy']);
|
||||
const {cx, cy} = a;
|
||||
({rx, ry} = a);
|
||||
if (elem.tagName === 'circle') {
|
||||
rx = ry = $(elem).attr('r');
|
||||
ry = $(elem).attr('r');
|
||||
rx = ry;
|
||||
}
|
||||
|
||||
d = getPathDFromSegments([
|
||||
|
@ -736,7 +750,7 @@ export const getPathDFromElement = function (elem) {
|
|||
['Z', []]
|
||||
]);
|
||||
break;
|
||||
case 'path':
|
||||
} case 'path':
|
||||
d = elem.getAttribute('d');
|
||||
break;
|
||||
case 'line':
|
||||
|
@ -749,11 +763,13 @@ export const getPathDFromElement = function (elem) {
|
|||
case 'polygon':
|
||||
d = 'M' + elem.getAttribute('points') + ' Z';
|
||||
break;
|
||||
case 'rect':
|
||||
case 'rect': {
|
||||
const r = $(elem).attr(['rx', 'ry']);
|
||||
({rx, ry} = r);
|
||||
const b = elem.getBBox();
|
||||
const {x, y} = b, w = b.width, h = b.height;
|
||||
const {x, y} = b,
|
||||
w = b.width,
|
||||
h = b.height;
|
||||
num = 4 - num; // Why? Because!
|
||||
|
||||
if (!rx && !ry) {
|
||||
|
@ -781,7 +797,7 @@ export const getPathDFromElement = function (elem) {
|
|||
]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -826,11 +842,11 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat
|
|||
path.setAttribute('transform', eltrans);
|
||||
}
|
||||
|
||||
const parent = elem.parentNode;
|
||||
const {parentNode} = elem;
|
||||
if (elem.nextSibling) {
|
||||
elem.before(path);
|
||||
} else {
|
||||
parent.append(path);
|
||||
parentNode.append(path);
|
||||
}
|
||||
|
||||
const d = getPathDFromElement(elem);
|
||||
|
@ -861,12 +877,12 @@ export const getBBoxOfElementAsPath = function (elem, addSVGElementFromJson, pat
|
|||
* @param {module:path.pathActions} pathActions - If a transform exists, pathActions.resetOrientation() is used. See: canvas.pathActions.
|
||||
* @param {module:draw.DrawCanvasInit#clearSelection|module:path.EditorContext#clearSelection} clearSelection - see [canvas.clearSelection]{@link module:svgcanvas.SvgCanvas#clearSelection}
|
||||
* @param {module:path.EditorContext#addToSelection} addToSelection - see [canvas.addToSelection]{@link module:svgcanvas.SvgCanvas#addToSelection}
|
||||
* @param {module:history} history - see history module
|
||||
* @param {module:history} hstry - see history module
|
||||
* @param {module:path.EditorContext#addCommandToHistory|module:draw.DrawCanvasInit#addCommandToHistory} addCommandToHistory - see [canvas.addCommandToHistory]{@link module:svgcanvas~addCommandToHistory}
|
||||
* @returns {SVGPathElement|null} The converted path element or null if the DOM element was not recognized.
|
||||
*/
|
||||
export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, history, addCommandToHistory) {
|
||||
const batchCmd = new history.BatchCommand('Convert element to Path');
|
||||
export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathActions, clearSelection, addToSelection, hstry, addCommandToHistory) {
|
||||
const batchCmd = new hstry.BatchCommand('Convert element to Path');
|
||||
|
||||
// Any attribute on the element not covered by the passed-in attributes
|
||||
attrs = $.extend({}, attrs, getExtraAttributesForConvertToPath(elem));
|
||||
|
@ -882,11 +898,11 @@ export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathA
|
|||
}
|
||||
|
||||
const {id} = elem;
|
||||
const parent = elem.parentNode;
|
||||
const {parentNode} = elem;
|
||||
if (elem.nextSibling) {
|
||||
elem.before(path);
|
||||
} else {
|
||||
parent.append(path);
|
||||
parentNode.append(path);
|
||||
}
|
||||
|
||||
const d = getPathDFromElement(elem);
|
||||
|
@ -939,14 +955,14 @@ export const convertToPath = function (elem, attrs, addSVGElementFromJson, pathA
|
|||
* getBBox then apply the angle and any transforms.
|
||||
*
|
||||
* @param {Float} angle - The rotation angle in degrees
|
||||
* @param {boolean} hasMatrixTransform - True if there is a matrix transform
|
||||
* @param {boolean} hasAMatrixTransform - True if there is a matrix transform
|
||||
* @returns {boolean} True if the bbox can be optimized.
|
||||
*/
|
||||
function bBoxCanBeOptimizedOverNativeGetBBox (angle, hasMatrixTransform) {
|
||||
function bBoxCanBeOptimizedOverNativeGetBBox (angle, hasAMatrixTransform) {
|
||||
const angleModulo90 = angle % 90;
|
||||
const closeTo90 = angleModulo90 < -89.99 || angleModulo90 > 89.99;
|
||||
const closeTo0 = angleModulo90 > -0.001 && angleModulo90 < 0.001;
|
||||
return hasMatrixTransform || !(closeTo0 || closeTo90);
|
||||
return hasAMatrixTransform || !(closeTo0 || closeTo90);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -979,13 +995,15 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA
|
|||
// TODO: why ellipse and not circle
|
||||
const elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon'];
|
||||
if (elemNames.includes(elem.tagName)) {
|
||||
bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);
|
||||
goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);
|
||||
bb = goodBb;
|
||||
} else if (elem.tagName === 'rect') {
|
||||
// Look for radius
|
||||
const rx = elem.getAttribute('rx');
|
||||
const ry = elem.getAttribute('ry');
|
||||
if (rx || ry) {
|
||||
bb = goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);
|
||||
goodBb = getBBoxOfElementAsPath(elem, addSVGElementFromJson, pathActions);
|
||||
bb = goodBb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1012,7 +1030,12 @@ export const getBBoxWithTransform = function (elem, addSVGElementFromJson, pathA
|
|||
return bb;
|
||||
};
|
||||
|
||||
// TODO: This is problematic with large stroke-width and, for example, a single horizontal line. The calculated BBox extends way beyond left and right sides.
|
||||
/**
|
||||
* @param {Element} elem
|
||||
* @returns {Float}
|
||||
* @todo This is problematic with large stroke-width and, for example, a single
|
||||
* horizontal line. The calculated BBox extends way beyond left and right sides.
|
||||
*/
|
||||
function getStrokeOffsetForBBox (elem) {
|
||||
const sw = elem.getAttribute('stroke-width');
|
||||
return (!isNaN(sw) && elem.getAttribute('stroke') !== 'none') ? sw / 2 : 0;
|
||||
|
@ -1090,16 +1113,16 @@ export const getStrokedBBox = function (elems, addSVGElementFromJson, pathAction
|
|||
* Note that 0-opacity, off-screen etc elements are still considered "visible"
|
||||
* for this function.
|
||||
* @function module:utilities.getVisibleElements
|
||||
* @param {Element} parent - The parent DOM element to search within
|
||||
* @param {Element} parentElement - The parent DOM element to search within
|
||||
* @returns {Element[]} All "visible" elements.
|
||||
*/
|
||||
export const getVisibleElements = function (parent) {
|
||||
if (!parent) {
|
||||
parent = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included
|
||||
export const getVisibleElements = function (parentElement) {
|
||||
if (!parentElement) {
|
||||
parentElement = $(editorContext_.getSVGContent()).children(); // Prevent layers from being included
|
||||
}
|
||||
|
||||
const contentElems = [];
|
||||
$(parent).children().each(function (i, elem) {
|
||||
$(parentElement).children().each(function (i, elem) {
|
||||
if (elem.getBBox) {
|
||||
contentElems.push(elem);
|
||||
}
|
||||
|
@ -1148,7 +1171,7 @@ export const getRotationAngleFromTransformList = function (tlist, toRad) {
|
|||
* @param {boolean} [toRad=false] - When true returns the value in radians rather than degrees
|
||||
* @returns {Float} The angle in degrees or radians
|
||||
*/
|
||||
export let getRotationAngle = function (elem, toRad) {
|
||||
export let getRotationAngle = function (elem, toRad) { // eslint-disable-line import/no-mutable-exports
|
||||
const selected = elem || editorContext_.getSelectedElements()[0];
|
||||
// find the rotation transform (if any) and set it
|
||||
const tlist = getTransformList(selected);
|
||||
|
@ -1169,13 +1192,14 @@ export const getRefElem = function (attrVal) {
|
|||
* Get a DOM element by ID within the SVG root element.
|
||||
* @function module:utilities.getElem
|
||||
* @param {string} id - String with the element's new ID
|
||||
* @returns {Element}
|
||||
* @returns {?Element}
|
||||
*/
|
||||
export const getElem = (supportsSelectors())
|
||||
? function (id) {
|
||||
// querySelector lookup
|
||||
return svgroot_.querySelector('#' + id);
|
||||
} : supportsXpath()
|
||||
}
|
||||
: supportsXpath()
|
||||
? function (id) {
|
||||
// xpath lookup
|
||||
return domdoc_.evaluate(
|
||||
|
@ -1183,7 +1207,8 @@ export const getElem = (supportsSelectors())
|
|||
domcontainer_,
|
||||
function () { return NS.SVG; },
|
||||
9,
|
||||
null).singleNodeValue;
|
||||
null
|
||||
).singleNodeValue;
|
||||
}
|
||||
: function (id) {
|
||||
// jQuery lookup: twice as slow as xpath in FF
|
||||
|
@ -1242,12 +1267,11 @@ export const cleanupElement = function (element) {
|
|||
delete defaults.ry;
|
||||
}
|
||||
|
||||
for (const attr in defaults) {
|
||||
const val = defaults[attr];
|
||||
Object.entries(defaults).forEach(([attr, val]) => {
|
||||
if (element.getAttribute(attr) === String(val)) {
|
||||
element.removeAttribute(attr);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1343,6 +1367,15 @@ export const copyElem = function (el, getNextId) {
|
|||
return newEl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether a value is `null` or `undefined`.
|
||||
* @param {Any} val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isNullish = (val) => {
|
||||
return val === null || val === undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Overwrite methods for unit testing.
|
||||
* @function module:utilities.mock
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import svgEditor from './svg-editor.js';
|
||||
|
||||
svgEditor.setConfig({
|
||||
canvasName: 'xdomain', // Namespace this
|
||||
allowedOrigins: ['*']
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* Opens the dialog with the SVG Editor.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function startSvgEdit () { // eslint-disable-line no-unused-vars
|
||||
const url = 'chrome://svg-edit/content/editor/svg-editor.html';
|
||||
window.openDialog(url, 'SVG Editor', 'width=1024,height=700,menubar=no,toolbar=no');
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
jQuery(function () {
|
||||
if (!window.Components) return;
|
||||
|
||||
/**
|
||||
* Offer choice of file.
|
||||
* @param {boolean} readflag
|
||||
* @returns {nsILocalFile}
|
||||
*/
|
||||
function mozFilePicker (readflag) {
|
||||
const fp = window.Components.classes['@mozilla.org/filepicker;1']
|
||||
.createInstance(Components.interfaces.nsIFilePicker);
|
||||
|
@ -19,16 +24,16 @@ jQuery(function () {
|
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const file = mozFilePicker(true);
|
||||
if (!file) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const inputStream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
|
||||
inputStream.init(file, 0x01, parseInt('00004', 8), null);
|
||||
inputStream.init(file, 0x01, 0o00004, null);
|
||||
const sInputStream = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
sInputStream.init(inputStream);
|
||||
svgCanvas.setSvgString(sInputStream.read(sInputStream.available()));
|
||||
} catch (e) {
|
||||
console.log('Exception while attempting to load' + e);
|
||||
console.log('Exception while attempting to load' + e); // eslint-disable-line no-console
|
||||
}
|
||||
},
|
||||
save (svg, str) {
|
||||
|
@ -39,16 +44,16 @@ jQuery(function () {
|
|||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
file.create(0, parseInt('0664', 8));
|
||||
file.create(0, 0o0664);
|
||||
}
|
||||
|
||||
const out = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
out.init(file, 0x20 | 0x02, parseInt('00004', 8), null);
|
||||
out.init(file, 0x20 | 0x02, 0o00004, null); // eslint-disable-line no-bitwise
|
||||
out.write(str, str.length);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
alert(e); // eslint-disable-line no-alert
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* @todo Fork find-in-files to get ignore pattern support
|
||||
*/
|
||||
const fif = require('find-in-files');
|
||||
|
||||
(async () => {
|
||||
/**
|
||||
* @typedef {PlainObject} FileResult
|
||||
|
@ -15,7 +16,7 @@ const fileMatchPatterns = ['editor'];
|
|||
* Keys are file name strings
|
||||
* @type {Object.<string, FileResult>}
|
||||
*/
|
||||
let results = await Promise.all(fileMatchPatterns.map(async (fileMatchPattern) => {
|
||||
let results = await Promise.all(fileMatchPatterns.map((fileMatchPattern) => {
|
||||
return fif.find(
|
||||
{
|
||||
// We grab to the end of the line as the `line` result for `find-in-files`
|
||||
|
@ -46,22 +47,28 @@ Object.entries(results).forEach(([file, res]) => {
|
|||
});
|
||||
*/
|
||||
});
|
||||
console.log(`${output}\nTotal failures found: ${total}.\n`);
|
||||
console.log(`${output}\nTotal failures found: ${total}.\n`); // eslint-disable-line no-console
|
||||
|
||||
/**
|
||||
* @external FindInFilesResult
|
||||
* @type {PlainObject}
|
||||
* @property {string[]} matches The matched strings
|
||||
* @property {Integer} count The number of matches
|
||||
* @property {string[]} line The lines that were matched. The docs mistakenly indicate the property is named `lines`; see {@link https://github.com/kaesetoast/find-in-files/pull/19}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Eliminates known false matches against overly generic types.
|
||||
* @param {string} file
|
||||
* @param {external:FindInFilesResult} res
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function reduceFalseMatches (file, res) {
|
||||
switch (file) {
|
||||
case 'editor/external/jamilih/jml-es.js':
|
||||
case 'editor/xdomain-svgedit-config-iife.js': // Ignore
|
||||
res.line = [];
|
||||
break;
|
||||
case 'editor/external/dynamic-import-polyfill/importModule.js':
|
||||
res.line = res.line.filter((line) => {
|
||||
return ![
|
||||
'* @returns {*} The return depends on the export of the targeted module.',
|
||||
'* @returns {ArbitraryModule|*} The return depends on the export of the targeted module.'
|
||||
].includes(line);
|
||||
});
|
||||
break;
|
||||
case 'editor/embedapi.js':
|
||||
res.line = res.line.filter((line) => {
|
||||
return ![
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue