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